summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter/google-breakpad/src/common
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-04-01 13:55:00 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-04-01 13:55:00 -0400
commitce3979c721ba378a448bfbe3671c99d993cbc801 (patch)
treee200d5225bcecef5f974b946a58277fddd24e89c /toolkit/crashreporter/google-breakpad/src/common
parentf6c16cff36048c583ca0e1d019b622336ca861a0 (diff)
parentff2f287f82630ab3887d7d5c1e64e5b888ea0beb (diff)
downloadUXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar
UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.gz
UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.lz
UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.xz
UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.zip
Merge branch 'master' into Sync-weave
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/common')
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/Makefile.in9
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S489
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext_unittest.cc186
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h168
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/link.h73
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/sgidefs.h41
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/stab.h100
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/sys/procfs.h124
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/sys/signal.h35
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h85
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/include/ucontext.h56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/testing/include/wchar.h76
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/testing/mkdtemp.h110
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/testing/pthread_fixes.h99
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/android/ucontext_constants.h144
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc487
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h114
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc209
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h119
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/basictypes.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/byte_cursor.h265
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/byte_cursor_unittest.cc776
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/common.gyp250
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c554
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h164
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h170
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc250
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h315
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader_unittest.cc707
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc198
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h269
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc199
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h365
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler_unittest.cc527
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h675
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc2734
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h1288
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc2468
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc487
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_test_common.h149
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.cc1273
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h166
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc231
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h188
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h61
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/moz.build35
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h51
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc295
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h202
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module_unittest.cc306
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc1075
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h320
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc1804
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.cc143
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.h188
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module_unittest.cc391
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/language.cc83
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/language.h88
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc70
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc1159
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h86
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc204
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc179
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h148
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc256
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h46
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc178
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc370
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h74
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc194
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h126
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc202
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h87
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc338
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc202
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h107
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc170
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc104
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h48
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc230
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h90
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h40
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc241
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h93
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc237
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h96
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc213
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc107
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h87
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc208
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/moz.build56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc53
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h65
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc89
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc155
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h59
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc263
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc413
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h124
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc322
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h117
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig52
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig32
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig34
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h456
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h504
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m611
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h61
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m269
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h301
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm306
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc211
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h47
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc42
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h54
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h73
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc646
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h196
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc106
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h81
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc84
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc369
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h131
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc539
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h460
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc1902
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc155
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h95
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc268
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h119
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/moz.build52
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc84
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h52
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h88
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h1110
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m428
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/md5.cc251
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/md5.h27
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/memory.h249
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/memory_range.h145
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/memory_range_unittest.cc193
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/memory_unittest.cc124
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h56
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module.cc348
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module.h351
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc616
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/moz.build72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h404
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.cc45
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h260
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc308
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc681
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.h49
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.h66
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.cc84
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.h50
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/message_output.h54
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/solaris/moz.build34
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc315
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h325
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc611
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.cc197
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.h143
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc258
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/stdio_wrapper.h43
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc155
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/string_conversion.h68
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/symbol_data.h42
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc359
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/test_assembler.h484
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/test_assembler_unittest.cc1662
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/testdata/func-line-pairing.h676
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/tests/auto_tempdir.h100
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.cc153
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.h52
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/unordered.h62
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/using_std_string.h65
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp105
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc92
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h64
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc76
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h58
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc420
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h129
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild15
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc694
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap.h72
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h137
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc330
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc1369
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h257
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h142
-rw-r--r--toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc133
200 files changed, 0 insertions, 55208 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in b/toolkit/crashreporter/google-breakpad/src/common/Makefile.in
deleted file mode 100644
index 44a1f79fd..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/Makefile.in
+++ /dev/null
@@ -1,9 +0,0 @@
-# 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/.
-
-include $(topsrcdir)/config/rules.mk
-
-# memory.h in this dir breaks things if -I$(srcdir) gets added, since memory.h
-# is also a system header and the copy here winds up getting included instead.
-INCLUDES := $(LOCAL_INCLUDES) -I$(DIST)/include
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S b/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S
deleted file mode 100644
index fd6326adf..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S
+++ /dev/null
@@ -1,489 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// A minimalistic implementation of getcontext() to be used by
-// Google Breakpad on Android.
-
-#include "common/android/ucontext_constants.h"
-
-/* int getcontext (ucontext_t *ucp) */
-
-#if defined(__arm__)
-
- .text
- .global breakpad_getcontext
- .hidden breakpad_getcontext
- .type breakpad_getcontext, #function
- .align 0
- .fnstart
-breakpad_getcontext:
-
- /* First, save r4-r11 */
- add r1, r0, #(MCONTEXT_GREGS_OFFSET + 4*4)
- stm r1, {r4-r11}
-
- /* r12 is a scratch register, don't save it */
-
- /* Save sp and lr explicitly. */
- /* - sp can't be stored with stmia in Thumb-2 */
- /* - STM instructions that store sp and pc are deprecated in ARM */
- str sp, [r0, #(MCONTEXT_GREGS_OFFSET + 13*4)]
- str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
-
- /* Save the caller's address in 'pc' */
- str lr, [r0, #(MCONTEXT_GREGS_OFFSET + 15*4)]
-
- /* Save ucontext_t* pointer across next call */
- mov r4, r0
-
- /* Call sigprocmask(SIG_BLOCK, NULL, &(ucontext->uc_sigmask)) */
- mov r0, #0 /* SIG_BLOCK */
- mov r1, #0 /* NULL */
- add r2, r4, #UCONTEXT_SIGMASK_OFFSET
- bl sigprocmask(PLT)
-
- /* Intentionally do not save the FPU state here. This is because on
- * Linux/ARM, one should instead use ptrace(PTRACE_GETFPREGS) or
- * ptrace(PTRACE_GETVFPREGS) to get it.
- *
- * Note that a real implementation of getcontext() would need to save
- * this here to allow setcontext()/swapcontext() to work correctly.
- */
-
- /* Restore the values of r4 and lr */
- mov r0, r4
- ldr lr, [r0, #(MCONTEXT_GREGS_OFFSET + 14*4)]
- ldr r4, [r0, #(MCONTEXT_GREGS_OFFSET + 4*4)]
-
- /* Return 0 */
- mov r0, #0
- bx lr
-
- .fnend
- .size breakpad_getcontext, . - breakpad_getcontext
-
-#elif defined(__aarch64__)
-
-#define _NSIG 64
-#define __NR_rt_sigprocmask 135
-
- .text
- .global breakpad_getcontext
- .hidden breakpad_getcontext
- .type breakpad_getcontext, #function
- .align 4
- .cfi_startproc
-breakpad_getcontext:
-
- /* The saved context will return to the getcontext() call point
- with a return value of 0 */
- str xzr, [x0, MCONTEXT_GREGS_OFFSET + 0 * REGISTER_SIZE]
-
- stp x18, x19, [x0, MCONTEXT_GREGS_OFFSET + 18 * REGISTER_SIZE]
- stp x20, x21, [x0, MCONTEXT_GREGS_OFFSET + 20 * REGISTER_SIZE]
- stp x22, x23, [x0, MCONTEXT_GREGS_OFFSET + 22 * REGISTER_SIZE]
- stp x24, x25, [x0, MCONTEXT_GREGS_OFFSET + 24 * REGISTER_SIZE]
- stp x26, x27, [x0, MCONTEXT_GREGS_OFFSET + 26 * REGISTER_SIZE]
- stp x28, x29, [x0, MCONTEXT_GREGS_OFFSET + 28 * REGISTER_SIZE]
- str x30, [x0, MCONTEXT_GREGS_OFFSET + 30 * REGISTER_SIZE]
-
- /* Place LR into the saved PC, this will ensure that when
- switching to this saved context with setcontext() control
- will pass back to the caller of getcontext(), we have
- already arranged to return the appropriate return value in x0
- above. */
- str x30, [x0, MCONTEXT_PC_OFFSET]
-
- /* Save the current SP */
- mov x2, sp
- str x2, [x0, MCONTEXT_SP_OFFSET]
-
- /* Initialize the pstate. */
- str xzr, [x0, MCONTEXT_PSTATE_OFFSET]
-
- /* Figure out where to place the first context extension
- block. */
- add x2, x0, #MCONTEXT_EXTENSION_OFFSET
-
- /* Write the context extension fpsimd header. */
- mov w3, #(FPSIMD_MAGIC & 0xffff)
- movk w3, #(FPSIMD_MAGIC >> 16), lsl #16
- str w3, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
- mov w3, #FPSIMD_CONTEXT_SIZE
- str w3, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
-
- /* Fill in the FP SIMD context. */
- add x3, x2, #(FPSIMD_CONTEXT_VREGS_OFFSET + 8 * SIMD_REGISTER_SIZE)
- stp d8, d9, [x3], #(2 * SIMD_REGISTER_SIZE)
- stp d10, d11, [x3], #(2 * SIMD_REGISTER_SIZE)
- stp d12, d13, [x3], #(2 * SIMD_REGISTER_SIZE)
- stp d14, d15, [x3], #(2 * SIMD_REGISTER_SIZE)
-
- add x3, x2, FPSIMD_CONTEXT_FPSR_OFFSET
-
- mrs x4, fpsr
- str w4, [x3]
-
- mrs x4, fpcr
- str w4, [x3, FPSIMD_CONTEXT_FPCR_OFFSET - FPSIMD_CONTEXT_FPSR_OFFSET]
-
- /* Write the termination context extension header. */
- add x2, x2, #FPSIMD_CONTEXT_SIZE
-
- str xzr, [x2, #FPSIMD_CONTEXT_MAGIC_OFFSET]
- str xzr, [x2, #FPSIMD_CONTEXT_SIZE_OFFSET]
-
- /* Grab the signal mask */
- /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
- add x2, x0, #UCONTEXT_SIGMASK_OFFSET
- mov x0, #0 /* SIG_BLOCK */
- mov x1, #0 /* NULL */
- mov x3, #(_NSIG / 8)
- mov x8, #__NR_rt_sigprocmask
- svc 0
-
- /* Return x0 for success */
- mov x0, 0
- ret
-
- .cfi_endproc
- .size breakpad_getcontext, . - breakpad_getcontext
-
-#elif defined(__i386__)
-
- .text
- .global breakpad_getcontext
- .hidden breakpad_getcontext
- .align 4
- .type breakpad_getcontext, @function
-
-breakpad_getcontext:
-
- movl 4(%esp), %eax /* eax = uc */
-
- /* Save register values */
- movl %ecx, MCONTEXT_ECX_OFFSET(%eax)
- movl %edx, MCONTEXT_EDX_OFFSET(%eax)
- movl %ebx, MCONTEXT_EBX_OFFSET(%eax)
- movl %edi, MCONTEXT_EDI_OFFSET(%eax)
- movl %esi, MCONTEXT_ESI_OFFSET(%eax)
- movl %ebp, MCONTEXT_EBP_OFFSET(%eax)
-
- movl (%esp), %edx /* return address */
- lea 4(%esp), %ecx /* exclude return address from stack */
- mov %edx, MCONTEXT_EIP_OFFSET(%eax)
- mov %ecx, MCONTEXT_ESP_OFFSET(%eax)
-
- xorl %ecx, %ecx
- movw %fs, %cx
- mov %ecx, MCONTEXT_FS_OFFSET(%eax)
-
- movl $0, MCONTEXT_EAX_OFFSET(%eax)
-
- /* Save floating point state to fpregstate, then update
- * the fpregs pointer to point to it */
- leal UCONTEXT_FPREGS_MEM_OFFSET(%eax), %ecx
- fnstenv (%ecx)
- fldenv (%ecx)
- mov %ecx, UCONTEXT_FPREGS_OFFSET(%eax)
-
- /* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
- leal UCONTEXT_SIGMASK_OFFSET(%eax), %edx
- xorl %ecx, %ecx
- push %edx /* &uc->uc_sigmask */
- push %ecx /* NULL */
- push %ecx /* SIGBLOCK == 0 on i386 */
- call sigprocmask@PLT
- addl $12, %esp
-
- movl $0, %eax
- ret
-
- .size breakpad_getcontext, . - breakpad_getcontext
-
-#elif defined(__mips__)
-
-// This implementation is inspired by implementation of getcontext in glibc.
-#if _MIPS_SIM == _ABIO32
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/fpregdef.h>
-#else
-#include <machine/asm.h>
-#include <machine/regdef.h>
-#endif
-
-// from asm/asm.h
-#if _MIPS_SIM == _ABIO32
-#define ALSZ 7
-#define ALMASK ~7
-#define SZREG 4
-#else // _MIPS_SIM != _ABIO32
-#define ALSZ 15
-#define ALMASK ~15
-#define SZREG 8
-#endif
-
-#include <asm/unistd.h> // for __NR_rt_sigprocmask
-
-#define _NSIG8 128 / 8
-#define SIG_BLOCK 1
-
-
- .text
-LOCALS_NUM = 1 // save gp on stack
-FRAME_SIZE = ((LOCALS_NUM * SZREG) + ALSZ) & ALMASK
-
-GP_FRAME_OFFSET = FRAME_SIZE - (1 * SZREG)
-MCONTEXT_REG_SIZE = 8
-
-#if _MIPS_SIM == _ABIO32
-
-NESTED (breakpad_getcontext, FRAME_SIZE, ra)
- .mask 0x00000000, 0
- .fmask 0x00000000, 0
-
- .set noreorder
- .cpload t9
- .set reorder
-
- move a2, sp
-#define _SP a2
-
- addiu sp, -FRAME_SIZE
- .cprestore GP_FRAME_OFFSET
-
- sw s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw fp, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sw ra, MCONTEXT_PC_OFFSET(a0)
-
-#ifdef __mips_hard_float
- s.d fs0, (20 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d fs1, (22 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d fs2, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d fs3, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d fs4, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d fs5, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
-
- cfc1 v1, fcr31
- sw v1, MCONTEXT_FPC_CSR(a0)
-#endif // __mips_hard_float
-
- /* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
- li a3, _NSIG8
- addu a2, a0, UCONTEXT_SIGMASK_OFFSET
- move a1, zero
- li a0, SIG_BLOCK
- li v0, __NR_rt_sigprocmask
- syscall
-
- addiu sp, FRAME_SIZE
- jr ra
-
-END (breakpad_getcontext)
-#else
-
-#ifndef NESTED
-/*
- * NESTED - declare nested routine entry point
- */
-#define NESTED(symbol, framesize, rpc) \
- .globl symbol; \
- .align 2; \
- .type symbol,@function; \
- .ent symbol,0; \
-symbol: .frame sp, framesize, rpc;
-#endif
-
-/*
- * END - mark end of function
- */
-#ifndef END
-# define END(function) \
- .end function; \
- .size function,.-function
-#endif
-
-/* int getcontext (ucontext_t *ucp) */
-
-NESTED (breakpad_getcontext, FRAME_SIZE, ra)
- .mask 0x10000000, 0
- .fmask 0x00000000, 0
-
- move a2, sp
-#define _SP a2
- move a3, gp
-#define _GP a3
-
- daddiu sp, -FRAME_SIZE
- .cpsetup $25, GP_FRAME_OFFSET, breakpad_getcontext
-
- /* Store a magic flag. */
- li v1, 1
- sd v1, (0 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0) /* zero */
-
- sd s0, (16 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s1, (17 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s2, (18 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s3, (19 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s4, (20 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s5, (21 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s6, (22 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s7, (23 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd _GP, (28 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd _SP, (29 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd s8, (30 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd ra, (31 * MCONTEXT_REG_SIZE + MCONTEXT_GREGS_OFFSET)(a0)
- sd ra, MCONTEXT_PC_OFFSET(a0)
-
-#ifdef __mips_hard_float
- s.d $f24, (24 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f25, (25 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f26, (26 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f27, (27 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f28, (28 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f29, (29 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f30, (30 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
- s.d $f31, (31 * MCONTEXT_REG_SIZE + MCONTEXT_FPREGS_OFFSET)(a0)
-
- cfc1 v1, $31
- sw v1, MCONTEXT_FPC_CSR(a0)
-#endif /* __mips_hard_float */
-
-/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
- li a3, _NSIG8
- daddu a2, a0, UCONTEXT_SIGMASK_OFFSET
- move a1, zero
- li a0, SIG_BLOCK
-
- li v0, __NR_rt_sigprocmask
- syscall
-
- .cpreturn
- daddiu sp, FRAME_SIZE
- move v0, zero
- jr ra
-
-END (breakpad_getcontext)
-#endif // _MIPS_SIM == _ABIO32
-
-#elif defined(__x86_64__)
-/* The x64 implementation of breakpad_getcontext was derived in part
- from the implementation of libunwind which requires the following
- notice. */
-/* libunwind - a platform-independent unwind library
- Copyright (C) 2008 Google, Inc
- Contributed by Paul Pluzhnikov <ppluzhnikov@google.com>
- Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
- .text
- .global breakpad_getcontext
- .hidden breakpad_getcontext
- .align 4
- .type breakpad_getcontext, @function
-
-breakpad_getcontext:
- .cfi_startproc
-
- /* Callee saved: RBX, RBP, R12-R15 */
- movq %r12, MCONTEXT_GREGS_R12(%rdi)
- movq %r13, MCONTEXT_GREGS_R13(%rdi)
- movq %r14, MCONTEXT_GREGS_R14(%rdi)
- movq %r15, MCONTEXT_GREGS_R15(%rdi)
- movq %rbp, MCONTEXT_GREGS_RBP(%rdi)
- movq %rbx, MCONTEXT_GREGS_RBX(%rdi)
-
- /* Save argument registers (not strictly needed, but setcontext
- restores them, so don't restore garbage). */
- movq %r8, MCONTEXT_GREGS_R8(%rdi)
- movq %r9, MCONTEXT_GREGS_R9(%rdi)
- movq %rdi, MCONTEXT_GREGS_RDI(%rdi)
- movq %rsi, MCONTEXT_GREGS_RSI(%rdi)
- movq %rdx, MCONTEXT_GREGS_RDX(%rdi)
- movq %rax, MCONTEXT_GREGS_RAX(%rdi)
- movq %rcx, MCONTEXT_GREGS_RCX(%rdi)
-
- /* Save fp state (not needed, except for setcontext not
- restoring garbage). */
- leaq MCONTEXT_FPREGS_MEM(%rdi),%r8
- movq %r8, MCONTEXT_FPREGS_PTR(%rdi)
- fnstenv (%r8)
- stmxcsr FPREGS_OFFSET_MXCSR(%r8)
-
- leaq 8(%rsp), %rax /* exclude this call. */
- movq %rax, MCONTEXT_GREGS_RSP(%rdi)
-
- movq 0(%rsp), %rax
- movq %rax, MCONTEXT_GREGS_RIP(%rdi)
-
- /* Save signal mask: sigprocmask(SIGBLOCK, NULL, &uc->uc_sigmask) */
- leaq UCONTEXT_SIGMASK_OFFSET(%rdi), %rdx // arg3
- xorq %rsi, %rsi // arg2 NULL
- xorq %rdi, %rdi // arg1 SIGBLOCK == 0
- call sigprocmask@PLT
-
- /* Always return 0 for success, even if sigprocmask failed. */
- xorl %eax, %eax
- ret
- .cfi_endproc
- .size breakpad_getcontext, . - breakpad_getcontext
-
-#else
-#error "This file has not been ported for your CPU!"
-#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext_unittest.cc
deleted file mode 100644
index 2c550bf28..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext_unittest.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#if defined(__x86_64__)
-#include <asm/sigcontext.h>
-#endif
-
-#include <sys/ucontext.h>
-
-#include "breakpad_googletest_includes.h"
-#include "common/android/ucontext_constants.h"
-
-template <int left, int right>
-struct CompileAssertEquals {
- // a compilation error here indicates left and right are not equal.
- char left_too_large[right - left];
- // a compilation error here indicates left and right are not equal.
- char right_too_large[left - right];
-};
-
-#define COMPILE_ASSERT_EQ(left, right, tag) \
- CompileAssertEquals<left, right> tag;
-
-TEST(AndroidUContext, GRegsOffset) {
-#if defined(__arm__)
- // There is no gregs[] array on ARM, so compare to the offset of
- // first register fields, since they're stored in order.
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.arm_r0));
-#elif defined(__aarch64__)
- // There is no gregs[] array on ARM, so compare to the offset of
- // first register fields, since they're stored in order.
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.regs[0]));
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_SP_OFFSET),
- offsetof(ucontext_t,uc_mcontext.sp));
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
- offsetof(ucontext_t,uc_mcontext.pc));
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_PSTATE_OFFSET),
- offsetof(ucontext_t,uc_mcontext.pstate));
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_EXTENSION_OFFSET),
- offsetof(ucontext_t,uc_mcontext.__reserved));
-#elif defined(__i386__)
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.gregs));
-#define CHECK_REG(x) \
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_##x##_OFFSET), \
- offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]))
- CHECK_REG(GS);
- CHECK_REG(FS);
- CHECK_REG(ES);
- CHECK_REG(DS);
- CHECK_REG(EDI);
- CHECK_REG(ESI);
- CHECK_REG(EBP);
- CHECK_REG(ESP);
- CHECK_REG(EBX);
- CHECK_REG(EDX);
- CHECK_REG(ECX);
- CHECK_REG(EAX);
- CHECK_REG(TRAPNO);
- CHECK_REG(ERR);
- CHECK_REG(EIP);
- CHECK_REG(CS);
- CHECK_REG(EFL);
- CHECK_REG(UESP);
- CHECK_REG(SS);
-
- ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.fpregs));
-
- ASSERT_EQ(static_cast<size_t>(UCONTEXT_FPREGS_MEM_OFFSET),
- offsetof(ucontext_t,__fpregs_mem));
-#elif defined(__mips__)
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.gregs));
-
- // PC for mips is not part of gregs.
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_PC_OFFSET),
- offsetof(ucontext_t,uc_mcontext.pc));
-
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.fpregs));
-
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_FPC_CSR),
- offsetof(ucontext_t,uc_mcontext.fpc_csr));
-#elif defined(__x86_64__)
-
- COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.gregs),
- mcontext_gregs_offset);
-#define CHECK_REG(x) \
- COMPILE_ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_##x), \
- offsetof(ucontext_t,uc_mcontext.gregs[REG_##x]), reg_##x)
- CHECK_REG(R8);
- CHECK_REG(R9);
- CHECK_REG(R10);
- CHECK_REG(R11);
- CHECK_REG(R12);
- CHECK_REG(R13);
- CHECK_REG(R14);
- CHECK_REG(R15);
- CHECK_REG(RDI);
- CHECK_REG(RSI);
- CHECK_REG(RBP);
- CHECK_REG(RBX);
- CHECK_REG(RDX);
- CHECK_REG(RAX);
- CHECK_REG(RCX);
- CHECK_REG(RSP);
- CHECK_REG(RIP);
-
- // sigcontext is an analog to mcontext_t. The layout should be the same.
- COMPILE_ASSERT_EQ(offsetof(mcontext_t,fpregs),
- offsetof(sigcontext,fpstate), sigcontext_fpstate);
- // Check that _fpstate from asm/sigcontext.h is essentially the same
- // as _libc_fpstate.
- COMPILE_ASSERT_EQ(sizeof(_libc_fpstate), sizeof(_fpstate),
- sigcontext_fpstate_size);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,cwd),offsetof(_fpstate,cwd),
- sigcontext_fpstate_cwd);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,swd),offsetof(_fpstate,swd),
- sigcontext_fpstate_swd);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,ftw),offsetof(_fpstate,twd),
- sigcontext_fpstate_twd);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,fop),offsetof(_fpstate,fop),
- sigcontext_fpstate_fop);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rip),offsetof(_fpstate,rip),
- sigcontext_fpstate_rip);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,rdp),offsetof(_fpstate,rdp),
- sigcontext_fpstate_rdp);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcsr),offsetof(_fpstate,mxcsr),
- sigcontext_fpstate_mxcsr);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,mxcr_mask),
- offsetof(_fpstate,mxcsr_mask),
- sigcontext_fpstate_mxcsr_mask);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_st), offsetof(_fpstate,st_space),
- sigcontext_fpstate_stspace);
- COMPILE_ASSERT_EQ(offsetof(_libc_fpstate,_xmm), offsetof(_fpstate,xmm_space),
- sigcontext_fpstate_xmm_space);
-
- COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_PTR,
- offsetof(ucontext_t,uc_mcontext.fpregs),
- mcontext_fpregs_ptr);
- COMPILE_ASSERT_EQ(MCONTEXT_FPREGS_MEM, offsetof(ucontext_t,__fpregs_mem),
- mcontext_fpregs_mem);
- COMPILE_ASSERT_EQ(FPREGS_OFFSET_MXCSR, offsetof(_libc_fpstate,mxcsr),
- fpregs_offset_mxcsr);
- COMPILE_ASSERT_EQ(UCONTEXT_SIGMASK_OFFSET, offsetof(ucontext_t, uc_sigmask),
- ucontext_sigmask);
-#else
- ASSERT_EQ(static_cast<size_t>(MCONTEXT_GREGS_OFFSET),
- offsetof(ucontext_t,uc_mcontext.gregs));
-#endif
-}
-
-TEST(AndroidUContext, SigmakOffset) {
- ASSERT_EQ(static_cast<size_t>(UCONTEXT_SIGMASK_OFFSET),
- offsetof(ucontext_t,uc_sigmask));
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h
deleted file mode 100644
index b2a28df44..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/elf.h
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_INCLUDE_ELF_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
-
-#include <stdint.h>
-#include <libgen.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-// The Android <elf.h> provides BSD-based definitions for the ElfXX_Nhdr
-// types
-// always source-compatible with the GLibc/kernel ones. To overcome this
-// issue without modifying a lot of code in Breakpad, use an ugly macro
-// renaming trick with #include_next
-
-// Avoid conflict with BSD-based definition of ElfXX_Nhdr.
-// Unfortunately, their field member names do not use a 'n_' prefix.
-#define Elf32_Nhdr __bsd_Elf32_Nhdr
-#define Elf64_Nhdr __bsd_Elf64_Nhdr
-
-// In case they are defined by the NDK version
-#define Elf32_auxv_t __bionic_Elf32_auxv_t
-#define Elf64_auxv_t __bionic_Elf64_auxv_t
-
-#define Elf32_Dyn __bionic_Elf32_Dyn
-#define Elf64_Dyn __bionic_Elf64_Dyn
-
-#include_next <elf.h>
-
-#undef Elf32_Nhdr
-#undef Elf64_Nhdr
-
-typedef struct {
- Elf32_Word n_namesz;
- Elf32_Word n_descsz;
- Elf32_Word n_type;
-} Elf32_Nhdr;
-
-typedef struct {
- Elf64_Word n_namesz;
- Elf64_Word n_descsz;
- Elf64_Word n_type;
-} Elf64_Nhdr;
-
-#undef Elf32_auxv_t
-#undef Elf64_auxv_t
-
-typedef struct {
- uint32_t a_type;
- union {
- uint32_t a_val;
- } a_un;
-} Elf32_auxv_t;
-
-typedef struct {
- uint64_t a_type;
- union {
- uint64_t a_val;
- } a_un;
-} Elf64_auxv_t;
-
-#undef Elf32_Dyn
-#undef Elf64_Dyn
-
-typedef struct {
- Elf32_Sword d_tag;
- union {
- Elf32_Word d_val;
- Elf32_Addr d_ptr;
- } d_un;
-} Elf32_Dyn;
-
-typedef struct {
- Elf64_Sxword d_tag;
- union {
- Elf64_Xword d_val;
- Elf64_Addr d_ptr;
- } d_un;
-} Elf64_Dyn;
-
-
-// __WORDSIZE is GLibc-specific and used by Google Breakpad on Linux.
-#ifndef __WORDSIZE
-#if defined(__i386__) || defined(__ARM_EABI__) || defined(__mips__)
-#define __WORDSIZE 32
-#elif defined(__x86_64__) || defined(__aarch64__)
-#define __WORDSIZE 64
-#else
-#error "Unsupported Android CPU ABI"
-#endif
-#endif
-
-// The Android headers don't always define this constant.
-#ifndef EM_X86_64
-#define EM_X86_64 62
-#endif
-
-#ifndef EM_PPC64
-#define EM_PPC64 21
-#endif
-
-#ifndef EM_S390
-#define EM_S390 22
-#endif
-
-#if !defined(AT_SYSINFO_EHDR)
-#define AT_SYSINFO_EHDR 33
-#endif
-
-#if !defined(NT_PRSTATUS)
-#define NT_PRSTATUS 1
-#endif
-
-#if !defined(NT_PRPSINFO)
-#define NT_PRPSINFO 3
-#endif
-
-#if !defined(NT_AUXV)
-#define NT_AUXV 6
-#endif
-
-#if !defined(NT_PRXFPREG)
-#define NT_PRXFPREG 0x46e62b7f
-#endif
-
-#if !defined(NT_FPREGSET)
-#define NT_FPREGSET 2
-#endif
-
-#if !defined(SHT_MIPS_DWARF)
-#define SHT_MIPS_DWARF 0x7000001e
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_ELF_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/link.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/link.h
deleted file mode 100644
index 0f7d98e75..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/link.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2012, 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_ANDROID_INCLUDE_LINK_H
-#define GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H
-
-/* Android doesn't provide all the data-structures required in its <link.h>.
- Provide custom version here. */
-#include_next <link.h>
-
-// TODO(rmcilroy): Remove this file once the ndk is updated for other
-// architectures - crbug.com/358831
-#if !defined(__aarch64__) && !defined(__x86_64__) && \
- !(defined(__mips__) && _MIPS_SIM == _ABI64)
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#if defined(ANDROID) && ANDROID_VERSION <= 20
-struct r_debug {
- int r_version;
- struct link_map* r_map;
- ElfW(Addr) r_brk;
- enum {
- RT_CONSISTENT,
- RT_ADD,
- RT_DELETE } r_state;
- ElfW(Addr) r_ldbase;
-};
-
-struct link_map {
- ElfW(Addr) l_addr;
- char* l_name;
- ElfW(Dyn)* l_ld;
- struct link_map* l_next;
- struct link_map* l_prev;
-};
-#endif
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // !defined(__aarch64__) && !defined(__x86_64__)
-
-#endif /* GOOGLE_BREAKPAD_ANDROID_INCLUDE_LINK_H */
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/sgidefs.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/sgidefs.h
deleted file mode 100644
index 33796dcf7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/sgidefs.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 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 GOOGLE_BREAKPAD_ANDROID_INCLUDE_SGIDEFS_H
-#define GOOGLE_BREAKPAD_ANDROID_INCLUDE_SGIDEFS_H
-
-#ifdef __mips__
-
-// Android doesn't contain sgidefs.h, but does have <asm/sgidefs.h> which
-// contains what we need.
-#include <asm/sgidefs.h>
-
-#endif // __mips__
-
-#endif // GOOGLE_BREAKPAD_ANDROID_INCLUDE_SGIDEFS_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/stab.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/stab.h
deleted file mode 100644
index cd9290215..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/stab.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_INCLUDE_STAB_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_STAB_H
-
-#include <sys/cdefs.h>
-
-#ifdef __BIONIC_HAVE_STAB_H
-#include <stab.h>
-#else
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#define _STAB_CODE_LIST \
- _STAB_CODE_DEF(UNDF,0x00) \
- _STAB_CODE_DEF(GSYM,0x20) \
- _STAB_CODE_DEF(FNAME,0x22) \
- _STAB_CODE_DEF(FUN,0x24) \
- _STAB_CODE_DEF(STSYM,0x26) \
- _STAB_CODE_DEF(LCSYM,0x28) \
- _STAB_CODE_DEF(MAIN,0x2a) \
- _STAB_CODE_DEF(PC,0x30) \
- _STAB_CODE_DEF(NSYMS,0x32) \
- _STAB_CODE_DEF(NOMAP,0x34) \
- _STAB_CODE_DEF(OBJ,0x38) \
- _STAB_CODE_DEF(OPT,0x3c) \
- _STAB_CODE_DEF(RSYM,0x40) \
- _STAB_CODE_DEF(M2C,0x42) \
- _STAB_CODE_DEF(SLINE,0x44) \
- _STAB_CODE_DEF(DSLINE,0x46) \
- _STAB_CODE_DEF(BSLINE,0x48) \
- _STAB_CODE_DEF(BROWS,0x48) \
- _STAB_CODE_DEF(DEFD,0x4a) \
- _STAB_CODE_DEF(EHDECL,0x50) \
- _STAB_CODE_DEF(MOD2,0x50) \
- _STAB_CODE_DEF(CATCH,0x54) \
- _STAB_CODE_DEF(SSYM,0x60) \
- _STAB_CODE_DEF(SO,0x64) \
- _STAB_CODE_DEF(LSYM,0x80) \
- _STAB_CODE_DEF(BINCL,0x82) \
- _STAB_CODE_DEF(SOL,0x84) \
- _STAB_CODE_DEF(PSYM,0xa0) \
- _STAB_CODE_DEF(EINCL,0xa2) \
- _STAB_CODE_DEF(ENTRY,0xa4) \
- _STAB_CODE_DEF(LBRAC,0xc0) \
- _STAB_CODE_DEF(EXCL,0xc2) \
- _STAB_CODE_DEF(SCOPE,0xc4) \
- _STAB_CODE_DEF(RBRAC,0xe0) \
- _STAB_CODE_DEF(BCOMM,0xe2) \
- _STAB_CODE_DEF(ECOMM,0xe4) \
- _STAB_CODE_DEF(ECOML,0xe8) \
- _STAB_CODE_DEF(NBTEXT,0xf0) \
- _STAB_CODE_DEF(NBDATA,0xf2) \
- _STAB_CODE_DEF(NBBSS,0xf4) \
- _STAB_CODE_DEF(NBSTS,0xf6) \
- _STAB_CODE_DEF(NBLCS,0xf8) \
- _STAB_CODE_DEF(LENG,0xfe)
-
-enum __stab_debug_code {
-#define _STAB_CODE_DEF(x,y) N_##x = y,
-_STAB_CODE_LIST
-#undef _STAB_CODE_DEF
-};
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // __BIONIC_HAVE_STAB_H
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_STAB_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/procfs.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/procfs.h
deleted file mode 100644
index 185124364..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/procfs.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_SYS_PROCFS_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_SYS_PROCFS_H
-
-#ifdef __BIONIC_HAVE_SYS_PROCFS_H
-
-#include_next <sys/procfs.h>
-
-#else
-
-#include <asm/ptrace.h>
-#include <sys/cdefs.h>
-#if defined (__mips__)
-#include <sys/types.h>
-#endif
-#include <sys/user.h>
-#include <unistd.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-#if defined(__x86_64__) || defined(__aarch64__)
-typedef unsigned long long elf_greg_t;
-#else
-typedef unsigned long elf_greg_t;
-#endif
-
-#ifdef __arm__
-#define ELF_NGREG (sizeof(struct user_regs) / sizeof(elf_greg_t))
-#elif defined(__aarch64__)
-#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
-#elif defined(__mips__)
-#define ELF_NGREG 45
-#else
-#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
-#endif
-
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-struct elf_siginfo {
- int si_signo;
- int si_code;
- int si_errno;
-};
-
-struct elf_prstatus {
- struct elf_siginfo pr_info;
- short pr_cursig;
- unsigned long pr_sigpend;
- unsigned long pr_sighold;
- pid_t pr_pid;
- pid_t pr_ppid;
- pid_t pr_pgrp;
- pid_t pd_sid;
- struct timeval pr_utime;
- struct timeval pr_stime;
- struct timeval pr_cutime;
- struct timeval pr_cstime;
- elf_gregset_t pr_reg;
- int pr_fpvalid;
-};
-
-#define ELF_PRARGSZ 80
-
-struct elf_prpsinfo {
- char pr_state;
- char pr_sname;
- char pr_zomb;
- char pr_nice;
- unsigned long pr_flags;
-#ifdef __x86_64__
- unsigned int pr_uid;
- unsigned int pr_gid;
-#elif defined(__mips__)
- __kernel_uid_t pr_uid;
- __kernel_gid_t pr_gid;
-#else
- unsigned short pr_uid;
- unsigned short pr_gid;
-#endif
- int pr_pid;
- int pr_ppid;
- int pr_pgrp;
- int pr_sid;
- char pr_fname[16];
- char pr_psargs[ELF_PRARGSZ];
-};
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // __BIONIC_HAVE_SYS_PROCFS_H
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_SYS_PROCFS_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/signal.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/signal.h
deleted file mode 100644
index 20c81e937..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/signal.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
-
-#include <signal.h>
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_SIGNAL_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h
deleted file mode 100644
index 1eb02a57d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/sys/user.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_INCLUDE_SYS_USER_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
-
-// The purpose of this file is to glue the mismatching headers (Android NDK vs
-// glibc) and therefore avoid doing otherwise awkward #ifdefs in the code.
-// The following quirks are currently handled by this file:
-// - i386: Use the Android NDK but alias user_fxsr_struct > user_fpxregs_struct.
-// - aarch64:
-// - NDK r10: Add missing user_regs_struct and user_fpsimd_struct structs.
-// - NDK r11+: Add missing <stdint.h> include
-// - Other platforms: Just use the Android NDK unchanged.
-
-// TODO(primiano): remove these changes after Chromium has stably rolled to
-// an NDK with the appropriate fixes.
-
-#if defined(ANDROID_NDK_MAJOR_VERSION) && ANDROID_NDK_MAJOR_VERSION > 10
-#ifdef __aarch64__
-#include <stdint.h>
-#endif // __aarch64__
-#endif // defined(ANDROID_NDK_MAJOR_VERSION) && ANDROID_NDK_MAJOR_VERSION > 10
-
-#include_next <sys/user.h>
-
-#ifdef __i386__
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-typedef struct user_fxsr_struct user_fpxregs_struct;
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-#endif // __i386__
-
-#if !defined(ANDROID_NDK_MAJOR_VERSION) || ANDROID_NDK_MAJOR_VERSION == 10
-#ifdef __aarch64__
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-struct user_regs_struct {
- __u64 regs[31];
- __u64 sp;
- __u64 pc;
- __u64 pstate;
-};
-struct user_fpsimd_struct {
- __uint128_t vregs[32];
- __u32 fpsr;
- __u32 fpcr;
-};
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-#endif // __aarch64__
-#endif // defined(ANDROID_NDK_VERSION) && ANDROID_NDK_MAJOR_VERSION == 10
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_SYS_USER_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/include/ucontext.h b/toolkit/crashreporter/google-breakpad/src/common/android/include/ucontext.h
deleted file mode 100644
index 29db8adee..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/include/ucontext.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012, 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_COMMON_ANDROID_INCLUDE_UCONTEXT_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
-
-#include <sys/cdefs.h>
-
-#ifdef __BIONIC_UCONTEXT_H
-#include <ucontext.h>
-#else
-
-#include <sys/ucontext.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-// Provided by src/android/common/breakpad_getcontext.S
-int breakpad_getcontext(ucontext_t* ucp);
-
-#define getcontext(x) breakpad_getcontext(x)
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-
-#endif // __BIONIC_UCONTEXT_H
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_INCLUDE_UCONTEXT_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/testing/include/wchar.h b/toolkit/crashreporter/google-breakpad/src/common/android/testing/include/wchar.h
deleted file mode 100644
index 85373fd2a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/testing/include/wchar.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// Android doesn't provide wcscasecmp(), so provide an alternative here.
-//
-// Note that this header is not needed when Breakpad is compiled against
-// a recent version of Googletest. It shall be considered for removal once
-// src/testing/ is updated to an appropriate revision in the future.
-
-#ifndef GOOGLEBREAKPAD_COMMON_ANDROID_INCLUDE_WCHAR_H
-#define GOOGLEBREAKPAD_COMMON_ANDROID_INCLUDE_WCHAR_H
-
-#include_next <wchar.h>
-
-#if !defined(__aarch64__) && !defined(__x86_64__) && \
- !(defined(__mips__) && _MIPS_SIM == _ABI64)
-
-// This needs to be in an extern "C" namespace, or Googletest will not
-// compile against it.
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
-
-static wchar_t inline wcstolower(wchar_t ch) {
- if (ch >= L'a' && ch <= L'A')
- ch -= L'a' - L'A';
- return ch;
-}
-
-static int inline wcscasecmp(const wchar_t* s1, const wchar_t* s2) {
- for (;;) {
- wchar_t c1 = wcstolower(*s1);
- wchar_t c2 = wcstolower(*s2);
- if (c1 < c2)
- return -1;
- if (c1 > c2)
- return 1;
- if (c1 == L'0')
- return 0;
- s1++;
- s2++;
- }
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
-#endif
-
-#endif // GOOGLEBREAKPAD_COMMON_ANDROID_INCLUDE_WCHAR_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/testing/mkdtemp.h b/toolkit/crashreporter/google-breakpad/src/common/android/testing/mkdtemp.h
deleted file mode 100644
index b86e2cd78..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/testing/mkdtemp.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// mkdtemp() wasn't declared in <stdlib.h> until NDK r9b due to a simple
-// packaging bug (the function has always been implemented in all versions
-// of the C library). This header is provided to build Breakpad with earlier
-// NDK revisions (e.g. the one used by Chromium). It may be removed in the
-// future once all major projects upgrade to use a more recent NDK.
-//
-// The reason this is inlined here is to avoid linking a new object file
-// into each unit test program (i.e. keep build files simple).
-
-#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_MKDTEMP_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_MKDTEMP_H
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-
-// Using a macro renaming trick here is necessary when building against
-// NDK r9b. Otherwise the compiler will complain that calls to mkdtemp()
-// are ambiguous.
-#define mkdtemp breakpad_mkdtemp
-
-namespace {
-
-char* breakpad_mkdtemp(char* path) {
- if (path == NULL) {
- errno = EINVAL;
- return NULL;
- }
-
- // 'path' must be terminated with six 'X'
- const char kSuffix[] = "XXXXXX";
- const size_t kSuffixLen = strlen(kSuffix);
- char* path_end = path + strlen(path);
-
- if (static_cast<size_t>(path_end - path) < kSuffixLen ||
- memcmp(path_end - kSuffixLen, kSuffix, kSuffixLen) != 0) {
- errno = EINVAL;
- return NULL;
- }
-
- // If 'path' contains a directory separator, check that it exists to
- // avoid looping later.
- char* sep = strrchr(path, '/');
- if (sep != NULL) {
- struct stat st;
- int ret;
- *sep = '\0'; // temporarily zero-terminate the dirname.
- ret = stat(path, &st);
- *sep = '/'; // restore full path.
- if (ret < 0)
- return NULL;
- if (!S_ISDIR(st.st_mode)) {
- errno = ENOTDIR;
- return NULL;
- }
- }
-
- // Loop. On each iteration, replace the XXXXXX suffix with a random
- // number.
- int tries;
- for (tries = 128; tries > 0; tries--) {
- int random = rand() % 1000000;
-
- snprintf(path_end - kSuffixLen, kSuffixLen + 1, "%0d", random);
- if (mkdir(path, 0700) == 0)
- return path; // Success
-
- if (errno != EEXIST)
- return NULL;
- }
-
- assert(errno == EEXIST);
- return NULL;
-}
-
-} // namespace
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_MKDTEMP_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/testing/pthread_fixes.h b/toolkit/crashreporter/google-breakpad/src/common/android/testing/pthread_fixes.h
deleted file mode 100644
index 15c6309ec..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/testing/pthread_fixes.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This contains Pthread-related functions not provided by the Android NDK
-// but required by the Breakpad unit test. The functions are inlined here
-// in a C++ anonymous namespace in order to keep the build files simples.
-
-#ifndef GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H
-#define GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H
-
-#include <pthread.h>
-
-namespace {
-
-// Android doesn't provide pthread_barrier_t for now.
-#ifndef PTHREAD_BARRIER_SERIAL_THREAD
-
-// Anything except 0 will do here.
-#define PTHREAD_BARRIER_SERIAL_THREAD 0x12345
-
-typedef struct {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- unsigned count;
-} pthread_barrier_t;
-
-int pthread_barrier_init(pthread_barrier_t* barrier,
- const void* /* barrier_attr */,
- unsigned count) {
- barrier->count = count;
- pthread_mutex_init(&barrier->mutex, NULL);
- pthread_cond_init(&barrier->cond, NULL);
- return 0;
-}
-
-int pthread_barrier_wait(pthread_barrier_t* barrier) {
- // Lock the mutex
- pthread_mutex_lock(&barrier->mutex);
- // Decrement the count. If this is the first thread to reach 0, wake up
- // waiters, unlock the mutex, then return PTHREAD_BARRIER_SERIAL_THREAD.
- if (--barrier->count == 0) {
- // First thread to reach the barrier
- pthread_cond_broadcast(&barrier->cond);
- pthread_mutex_unlock(&barrier->mutex);
- return PTHREAD_BARRIER_SERIAL_THREAD;
- }
- // Otherwise, wait for other threads until the count reaches 0, then
- // return 0 to indicate this is not the first thread.
- do {
- pthread_cond_wait(&barrier->cond, &barrier->mutex);
- } while (barrier->count > 0);
-
- pthread_mutex_unlock(&barrier->mutex);
- return 0;
-}
-
-int pthread_barrier_destroy(pthread_barrier_t *barrier) {
- barrier->count = 0;
- pthread_cond_destroy(&barrier->cond);
- pthread_mutex_destroy(&barrier->mutex);
- return 0;
-}
-
-#endif // defined(PTHREAD_BARRIER_SERIAL_THREAD)
-
-int pthread_yield(void) {
- sched_yield();
- return 0;
-}
-
-} // namespace
-
-#endif // GOOGLE_BREAKPAD_COMMON_ANDROID_TESTING_PTHREAD_FIXES_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/android/ucontext_constants.h b/toolkit/crashreporter/google-breakpad/src/common/android/ucontext_constants.h
deleted file mode 100644
index 1932d5739..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/android/ucontext_constants.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This header can be included either from a C, C++ or Assembly file.
-// Its purpose is to contain constants that must match the offsets of
-// various fields in ucontext_t.
-//
-// They should match the definitions from
-// src/common/android/include/sys/ucontext.h
-//
-// Used by src/common/android/breakpad_getcontext.S
-// Tested by src/common/android/testing/breakpad_getcontext_unittest.cc
-
-#ifndef GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
-#define GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
-
-#if defined(__arm__)
-
-#define MCONTEXT_GREGS_OFFSET 32
-#define UCONTEXT_SIGMASK_OFFSET 104
-
-#elif defined(__aarch64__)
-
-#define UCONTEXT_SIGMASK_OFFSET 40
-
-#define MCONTEXT_GREGS_OFFSET 184
-#define MCONTEXT_SP_OFFSET 432
-#define MCONTEXT_PC_OFFSET 440
-#define MCONTEXT_PSTATE_OFFSET 448
-#define MCONTEXT_EXTENSION_OFFSET 464
-
-#define FPSIMD_MAGIC 0x46508001
-
-#define FPSIMD_CONTEXT_MAGIC_OFFSET 0
-#define FPSIMD_CONTEXT_SIZE_OFFSET 4
-#define FPSIMD_CONTEXT_FPSR_OFFSET 8
-#define FPSIMD_CONTEXT_FPCR_OFFSET 12
-#define FPSIMD_CONTEXT_VREGS_OFFSET 16
-#define FPSIMD_CONTEXT_SIZE 528
-
-#define REGISTER_SIZE 8
-#define SIMD_REGISTER_SIZE 16
-
-#elif defined(__i386__)
-
-#define MCONTEXT_GREGS_OFFSET 20
-#define MCONTEXT_GS_OFFSET (MCONTEXT_GREGS_OFFSET + 0*4)
-#define MCONTEXT_FS_OFFSET (MCONTEXT_GREGS_OFFSET + 1*4)
-#define MCONTEXT_ES_OFFSET (MCONTEXT_GREGS_OFFSET + 2*4)
-#define MCONTEXT_DS_OFFSET (MCONTEXT_GREGS_OFFSET + 3*4)
-#define MCONTEXT_EDI_OFFSET (MCONTEXT_GREGS_OFFSET + 4*4)
-#define MCONTEXT_ESI_OFFSET (MCONTEXT_GREGS_OFFSET + 5*4)
-#define MCONTEXT_EBP_OFFSET (MCONTEXT_GREGS_OFFSET + 6*4)
-#define MCONTEXT_ESP_OFFSET (MCONTEXT_GREGS_OFFSET + 7*4)
-#define MCONTEXT_EBX_OFFSET (MCONTEXT_GREGS_OFFSET + 8*4)
-#define MCONTEXT_EDX_OFFSET (MCONTEXT_GREGS_OFFSET + 9*4)
-#define MCONTEXT_ECX_OFFSET (MCONTEXT_GREGS_OFFSET + 10*4)
-#define MCONTEXT_EAX_OFFSET (MCONTEXT_GREGS_OFFSET + 11*4)
-#define MCONTEXT_TRAPNO_OFFSET (MCONTEXT_GREGS_OFFSET + 12*4)
-#define MCONTEXT_ERR_OFFSET (MCONTEXT_GREGS_OFFSET + 13*4)
-#define MCONTEXT_EIP_OFFSET (MCONTEXT_GREGS_OFFSET + 14*4)
-#define MCONTEXT_CS_OFFSET (MCONTEXT_GREGS_OFFSET + 15*4)
-#define MCONTEXT_EFL_OFFSET (MCONTEXT_GREGS_OFFSET + 16*4)
-#define MCONTEXT_UESP_OFFSET (MCONTEXT_GREGS_OFFSET + 17*4)
-#define MCONTEXT_SS_OFFSET (MCONTEXT_GREGS_OFFSET + 18*4)
-
-#define UCONTEXT_SIGMASK_OFFSET 108
-
-#define UCONTEXT_FPREGS_OFFSET 96
-#define UCONTEXT_FPREGS_MEM_OFFSET 116
-
-#elif defined(__mips__)
-
-#if _MIPS_SIM == _ABIO32
-#define MCONTEXT_PC_OFFSET 32
-#define MCONTEXT_GREGS_OFFSET 40
-#define MCONTEXT_FPREGS_OFFSET 296
-#define MCONTEXT_FPC_CSR 556
-#define UCONTEXT_SIGMASK_OFFSET 616
-#else
-#define MCONTEXT_GREGS_OFFSET 40
-#define MCONTEXT_FPREGS_OFFSET 296
-#define MCONTEXT_PC_OFFSET 616
-#define MCONTEXT_FPC_CSR 624
-#define UCONTEXT_SIGMASK_OFFSET 640
-#endif
-
-#elif defined(__x86_64__)
-
-#define MCONTEXT_GREGS_OFFSET 40
-#define UCONTEXT_SIGMASK_OFFSET 296
-
-#define MCONTEXT_GREGS_R8 40
-#define MCONTEXT_GREGS_R9 48
-#define MCONTEXT_GREGS_R10 56
-#define MCONTEXT_GREGS_R11 64
-#define MCONTEXT_GREGS_R12 72
-#define MCONTEXT_GREGS_R13 80
-#define MCONTEXT_GREGS_R14 88
-#define MCONTEXT_GREGS_R15 96
-#define MCONTEXT_GREGS_RDI 104
-#define MCONTEXT_GREGS_RSI 112
-#define MCONTEXT_GREGS_RBP 120
-#define MCONTEXT_GREGS_RBX 128
-#define MCONTEXT_GREGS_RDX 136
-#define MCONTEXT_GREGS_RAX 144
-#define MCONTEXT_GREGS_RCX 152
-#define MCONTEXT_GREGS_RSP 160
-#define MCONTEXT_GREGS_RIP 168
-#define MCONTEXT_FPREGS_PTR 224
-#define MCONTEXT_FPREGS_MEM 304
-#define FPREGS_OFFSET_MXCSR 24
-
-#else
-#error "This header has not been ported for your CPU"
-#endif
-
-#endif // GOOGLEBREAKPAD_COMMON_ANDROID_UCONTEXT_CONSTANTS_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
deleted file mode 100644
index 2d1ed983d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.cc
+++ /dev/null
@@ -1,487 +0,0 @@
-
-/* libunwind - a platform-independent unwind library
- Copyright 2011 Linaro Limited
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-// 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.
-
-
-// Derived from libunwind, with extensive modifications.
-
-
-#include "common/arm_ex_reader.h"
-
-#include <assert.h>
-#include <stdio.h>
-
-// This file, in conjunction with arm_ex_to_module.cc, translates
-// EXIDX unwind information into the same format that Breakpad uses
-// for CFI information. Hence Breakpad's CFI unwinding abilities
-// also become usable for EXIDX.
-//
-// See: "Exception Handling ABI for the ARM Architecture", ARM IHI 0038A
-// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038a/IHI0038A_ehabi.pdf
-
-// EXIDX data is presented in two parts:
-//
-// * an index table. This contains two words per routine,
-// the first of which identifies the routine, and the second
-// of which is a reference to the unwind bytecode. If the
-// bytecode is very compact -- 3 bytes or less -- it can be
-// stored directly in the second word.
-//
-// * an area containing the unwind bytecodes.
-
-// General flow is: ExceptionTableInfo::Start iterates over all
-// of the index table entries (pairs). For each entry, it:
-//
-// * calls ExceptionTableInfo::ExtabEntryExtract to copy the bytecode
-// out into an intermediate buffer.
-
-// * uses ExceptionTableInfo::ExtabEntryDecode to parse the intermediate
-// buffer. Each bytecode instruction is bundled into a
-// arm_ex_to_module::extab_data structure, and handed to ..
-//
-// * .. ARMExToModule::ImproveStackFrame, which in turn hands it to
-// ARMExToModule::TranslateCmd, and that generates the pseudo-CFI
-// records that Breakpad stores.
-
-#define ARM_EXIDX_CANT_UNWIND 0x00000001
-#define ARM_EXIDX_COMPACT 0x80000000
-#define ARM_EXTBL_OP_FINISH 0xb0
-#define ARM_EXIDX_TABLE_LIMIT (255*4)
-
-namespace arm_ex_reader {
-
-using arm_ex_to_module::ARM_EXIDX_CMD_FINISH;
-using arm_ex_to_module::ARM_EXIDX_CMD_SUB_FROM_VSP;
-using arm_ex_to_module::ARM_EXIDX_CMD_ADD_TO_VSP;
-using arm_ex_to_module::ARM_EXIDX_CMD_REG_POP;
-using arm_ex_to_module::ARM_EXIDX_CMD_REG_TO_SP;
-using arm_ex_to_module::ARM_EXIDX_CMD_VFP_POP;
-using arm_ex_to_module::ARM_EXIDX_CMD_WREG_POP;
-using arm_ex_to_module::ARM_EXIDX_CMD_WCGR_POP;
-using arm_ex_to_module::ARM_EXIDX_CMD_RESERVED;
-using arm_ex_to_module::ARM_EXIDX_CMD_REFUSED;
-using arm_ex_to_module::exidx_entry;
-using arm_ex_to_module::ARM_EXIDX_VFP_SHIFT_16;
-using arm_ex_to_module::ARM_EXIDX_VFP_FSTMD;
-using google_breakpad::MemoryRange;
-
-
-static void* Prel31ToAddr(const void* addr) {
- uint32_t offset32 = *reinterpret_cast<const uint32_t*>(addr);
- // sign extend offset32[30:0] to 64 bits -- copy bit 30 to positions
- // 63:31 inclusive.
- uint64_t offset64 = offset32;
- if (offset64 & (1ULL << 30))
- offset64 |= 0xFFFFFFFF80000000ULL;
- else
- offset64 &= 0x000000007FFFFFFFULL;
- return ((char*)addr) + (uintptr_t)offset64;
-}
-
-
-// Extract unwind bytecode for the function denoted by |entry| into |buf|,
-// and return the number of bytes of |buf| written, along with a code
-// indicating the outcome.
-
-ExceptionTableInfo::ExExtractResult ExceptionTableInfo::ExtabEntryExtract(
- const struct exidx_entry* entry,
- uint8_t* buf, size_t buf_size,
- size_t* buf_used) {
- MemoryRange mr_out(buf, buf_size);
-
- *buf_used = 0;
-
-# define PUT_BUF_U8(_byte) \
- do { if (!mr_out.Covers(*buf_used, 1)) return ExOutBufOverflow; \
- buf[(*buf_used)++] = (_byte); } while (0)
-
-# define GET_EX_U32(_lval, _addr, _sec_mr) \
- do { if (!(_sec_mr).Covers(reinterpret_cast<const uint8_t*>(_addr) \
- - (_sec_mr).data(), 4)) \
- return ExInBufOverflow; \
- (_lval) = *(reinterpret_cast<const uint32_t*>(_addr)); } while (0)
-
-# define GET_EXIDX_U32(_lval, _addr) \
- GET_EX_U32(_lval, _addr, mr_exidx_)
-# define GET_EXTAB_U32(_lval, _addr) \
- GET_EX_U32(_lval, _addr, mr_extab_)
-
- uint32_t data;
- GET_EXIDX_U32(data, &entry->data);
-
- // A function can be marked CANT_UNWIND if (eg) it is known to be
- // at the bottom of the stack.
- if (data == ARM_EXIDX_CANT_UNWIND)
- return ExCantUnwind;
-
- uint32_t pers; // personality number
- uint32_t extra; // number of extra data words required
- uint32_t extra_allowed; // number of extra data words allowed
- uint32_t* extbl_data; // the handler entry, if not inlined
-
- if (data & ARM_EXIDX_COMPACT) {
- // The handler table entry has been inlined into the index table entry.
- // In this case it can only be an ARM-defined compact model, since
- // bit 31 is 1. Only personalities 0, 1 and 2 are defined for the
- // ARM compact model, but 1 and 2 are "Long format" and may require
- // extra data words. Hence the allowable personalities here are:
- // personality 0, in which case 'extra' has no meaning
- // personality 1, with zero extra words
- // personality 2, with zero extra words
- extbl_data = NULL;
- pers = (data >> 24) & 0x0F;
- extra = (data >> 16) & 0xFF;
- extra_allowed = 0;
- }
- else {
- // The index table entry is a pointer to the handler entry. Note
- // that Prel31ToAddr will read the given address, but we already
- // range-checked above.
- extbl_data = reinterpret_cast<uint32_t*>(Prel31ToAddr(&entry->data));
- GET_EXTAB_U32(data, extbl_data);
- if (!(data & ARM_EXIDX_COMPACT)) {
- // This denotes a "generic model" handler. That will involve
- // executing arbitary machine code, which is something we
- // can't represent here; hence reject it.
- return ExCantRepresent;
- }
- // So we have a compact model representation. Again, 3 possible
- // personalities, but this time up to 255 allowable extra words.
- pers = (data >> 24) & 0x0F;
- extra = (data >> 16) & 0xFF;
- extra_allowed = 255;
- extbl_data++;
- }
-
- // Now look at the the handler table entry. The first word is
- // |data| and subsequent words start at |*extbl_data|. The number
- // of extra words to use is |extra|, provided that the personality
- // allows extra words. Even if it does, none may be available --
- // extra_allowed is the maximum number of extra words allowed. */
- if (pers == 0) {
- // "Su16" in the documentation -- 3 unwinding insn bytes
- // |extra| has no meaning here; instead that byte is an unwind-info byte
- PUT_BUF_U8(data >> 16);
- PUT_BUF_U8(data >> 8);
- PUT_BUF_U8(data);
- }
- else if ((pers == 1 || pers == 2) && extra <= extra_allowed) {
- // "Lu16" or "Lu32" respectively -- 2 unwinding insn bytes,
- // and up to 255 extra words.
- PUT_BUF_U8(data >> 8);
- PUT_BUF_U8(data);
- for (uint32_t j = 0; j < extra; j++) {
- GET_EXTAB_U32(data, extbl_data);
- extbl_data++;
- PUT_BUF_U8(data >> 24);
- PUT_BUF_U8(data >> 16);
- PUT_BUF_U8(data >> 8);
- PUT_BUF_U8(data >> 0);
- }
- }
- else {
- // The entry is invalid.
- return ExInvalid;
- }
-
- // Make sure the entry is terminated with "FINISH"
- if (*buf_used > 0 && buf[(*buf_used) - 1] != ARM_EXTBL_OP_FINISH)
- PUT_BUF_U8(ARM_EXTBL_OP_FINISH);
-
- return ExSuccess;
-
-# undef GET_EXTAB_U32
-# undef GET_EXIDX_U32
-# undef GET_U32
-# undef PUT_BUF_U8
-}
-
-
-// Take the unwind information extracted by ExtabEntryExtract
-// and parse it into frame-unwind instructions. These are as
-// specified in "Table 4, ARM-defined frame-unwinding instructions"
-// in the specification document detailed in comments at the top
-// of this file.
-//
-// This reads from |buf[0, +data_size)|. It checks for overruns of
-// the input buffer and returns a negative value if that happens, or
-// for any other failure cases. It returns zero in case of success.
-int ExceptionTableInfo::ExtabEntryDecode(const uint8_t* buf, size_t buf_size) {
- if (buf == NULL || buf_size == 0)
- return -1;
-
- MemoryRange mr_in(buf, buf_size);
- const uint8_t* buf_initially = buf;
-
-# define GET_BUF_U8(_lval) \
- do { if (!mr_in.Covers(buf - buf_initially, 1)) return -1; \
- (_lval) = *(buf++); } while (0)
-
- const uint8_t* end = buf + buf_size;
-
- while (buf < end) {
- struct arm_ex_to_module::extab_data edata;
- memset(&edata, 0, sizeof(edata));
-
- uint8_t op;
- GET_BUF_U8(op);
- if ((op & 0xc0) == 0x00) {
- // vsp = vsp + (xxxxxx << 2) + 4
- edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
- edata.data = (((int)op & 0x3f) << 2) + 4;
- } else if ((op & 0xc0) == 0x40) {
- // vsp = vsp - (xxxxxx << 2) - 4
- edata.cmd = ARM_EXIDX_CMD_SUB_FROM_VSP;
- edata.data = (((int)op & 0x3f) << 2) + 4;
- } else if ((op & 0xf0) == 0x80) {
- uint8_t op2;
- GET_BUF_U8(op2);
- if (op == 0x80 && op2 == 0x00) {
- // Refuse to unwind
- edata.cmd = ARM_EXIDX_CMD_REFUSED;
- } else {
- // Pop up to 12 integer registers under masks {r15-r12},{r11-r4}
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- edata.data = ((op & 0xf) << 8) | op2;
- edata.data = edata.data << 4;
- }
- } else if ((op & 0xf0) == 0x90) {
- if (op == 0x9d || op == 0x9f) {
- // 9d: Reserved as prefix for ARM register to register moves
- // 9f: Reserved as perfix for Intel Wireless MMX reg to reg moves
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- } else {
- // Set vsp = r[nnnn]
- edata.cmd = ARM_EXIDX_CMD_REG_TO_SP;
- edata.data = op & 0x0f;
- }
- } else if ((op & 0xf0) == 0xa0) {
- // Pop r4 to r[4+nnn], or
- // Pop r4 to r[4+nnn] and r14 or
- unsigned end = (op & 0x07);
- edata.data = (1 << (end + 1)) - 1;
- edata.data = edata.data << 4;
- if (op & 0x08) edata.data |= 1 << 14;
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- } else if (op == ARM_EXTBL_OP_FINISH) {
- // Finish
- edata.cmd = ARM_EXIDX_CMD_FINISH;
- buf = end;
- } else if (op == 0xb1) {
- uint8_t op2;
- GET_BUF_U8(op2);
- if (op2 == 0 || (op2 & 0xf0)) {
- // Spare
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- } else {
- // Pop integer registers under mask {r3,r2,r1,r0}
- edata.cmd = ARM_EXIDX_CMD_REG_POP;
- edata.data = op2 & 0x0f;
- }
- } else if (op == 0xb2) {
- // vsp = vsp + 0x204 + (uleb128 << 2)
- uint64_t offset = 0;
- uint8_t byte, shift = 0;
- do {
- GET_BUF_U8(byte);
- offset |= (byte & 0x7f) << shift;
- shift += 7;
- } while ((byte & 0x80) && buf < end);
- edata.data = offset * 4 + 0x204;
- edata.cmd = ARM_EXIDX_CMD_ADD_TO_VSP;
- } else if (op == 0xb3 || op == 0xc8 || op == 0xc9) {
- // b3: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDX-ishly
- // c8: Pop VFP regs D[16+ssss] to D[16+ssss+cccc], FSTMFDD-ishly
- // c9: Pop VFP regs D[ssss] to D[ssss+cccc], FSTMFDD-ishly
- edata.cmd = ARM_EXIDX_CMD_VFP_POP;
- GET_BUF_U8(edata.data);
- if (op == 0xc8) edata.data |= ARM_EXIDX_VFP_SHIFT_16;
- if (op != 0xb3) edata.data |= ARM_EXIDX_VFP_FSTMD;
- } else if ((op & 0xf8) == 0xb8 || (op & 0xf8) == 0xd0) {
- // b8: Pop VFP regs D[8] to D[8+nnn], FSTMFDX-ishly
- // d0: Pop VFP regs D[8] to D[8+nnn], FSTMFDD-ishly
- edata.cmd = ARM_EXIDX_CMD_VFP_POP;
- edata.data = 0x80 | (op & 0x07);
- if ((op & 0xf8) == 0xd0) edata.data |= ARM_EXIDX_VFP_FSTMD;
- } else if (op >= 0xc0 && op <= 0xc5) {
- // Intel Wireless MMX pop wR[10]-wr[10+nnn], nnn != 6,7
- edata.cmd = ARM_EXIDX_CMD_WREG_POP;
- edata.data = 0xa0 | (op & 0x07);
- } else if (op == 0xc6) {
- // Intel Wireless MMX pop wR[ssss] to wR[ssss+cccc]
- edata.cmd = ARM_EXIDX_CMD_WREG_POP;
- GET_BUF_U8(edata.data);
- } else if (op == 0xc7) {
- uint8_t op2;
- GET_BUF_U8(op2);
- if (op2 == 0 || (op2 & 0xf0)) {
- // Spare
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- } else {
- // Intel Wireless MMX pop wCGR registers under mask {wCGR3,2,1,0}
- edata.cmd = ARM_EXIDX_CMD_WCGR_POP;
- edata.data = op2 & 0x0f;
- }
- } else {
- // Spare
- edata.cmd = ARM_EXIDX_CMD_RESERVED;
- }
-
- int ret = handler_->ImproveStackFrame(&edata);
- if (ret < 0)
- return ret;
- }
- return 0;
-
-# undef GET_BUF_U8
-}
-
-void ExceptionTableInfo::Start() {
- const struct exidx_entry* start
- = reinterpret_cast<const struct exidx_entry*>(mr_exidx_.data());
- const struct exidx_entry* end
- = reinterpret_cast<const struct exidx_entry*>(mr_exidx_.data()
- + mr_exidx_.length());
-
- // Iterate over each of the EXIDX entries (pairs of 32-bit words).
- // These occupy the entire .exidx section.
- for (const struct exidx_entry* entry = start; entry < end; ++entry) {
- // Figure out the code address range that this table entry is
- // associated with.
- uint32_t addr = (reinterpret_cast<char*>(Prel31ToAddr(&entry->addr))
- - mapping_addr_ + loading_addr_) & 0x7fffffff;
- uint32_t next_addr;
- if (entry < end - 1) {
- next_addr = (reinterpret_cast<char*>(Prel31ToAddr(&((entry + 1)->addr)))
- - mapping_addr_ + loading_addr_) & 0x7fffffff;
- } else {
- // This is the last EXIDX entry in the sequence, so we don't
- // have an address for the start of the next function, to limit
- // this one. Instead use the address of the last byte of the
- // text section associated with this .exidx section, that we
- // have been given. So as to avoid junking up the CFI unwind
- // tables with absurdly large address ranges in the case where
- // text_last_svma_ is wrong, only use the value if it is nonzero
- // and within one page of |addr|. Otherwise assume a length of 1.
- //
- // In some cases, gcc has been observed to finish the exidx
- // section with an entry of length 1 marked CANT_UNWIND,
- // presumably exactly for the purpose of giving a definite
- // length for the last real entry, without having to look at
- // text segment boundaries.
- bool plausible = false;
- next_addr = addr + 1;
- if (text_last_svma_ != 0) {
- uint32_t maybe_next_addr = text_last_svma_ + 1;
- if (maybe_next_addr > addr && maybe_next_addr - addr <= 4096) {
- next_addr = maybe_next_addr;
- plausible = true;
- }
- }
- if (!plausible) {
- fprintf(stderr, "ExceptionTableInfo: implausible EXIDX last entry size "
- "%d, using 1 instead.", (int32_t)(text_last_svma_ - addr));
- }
- }
-
- // Extract the unwind info into |buf|. This might fail for
- // various reasons. It involves reading both the .exidx and
- // .extab sections. All accesses to those sections are
- // bounds-checked.
- uint8_t buf[ARM_EXIDX_TABLE_LIMIT];
- size_t buf_used = 0;
- ExExtractResult res = ExtabEntryExtract(entry, buf, sizeof(buf), &buf_used);
- if (res != ExSuccess) {
- // Couldn't extract the unwind info, for some reason. Move on.
- switch (res) {
- case ExInBufOverflow:
- fprintf(stderr, "ExtabEntryExtract: .exidx/.extab section overrun");
- break;
- case ExOutBufOverflow:
- fprintf(stderr, "ExtabEntryExtract: bytecode buffer overflow");
- break;
- case ExCantUnwind:
- fprintf(stderr, "ExtabEntryExtract: function is marked CANT_UNWIND");
- break;
- case ExCantRepresent:
- fprintf(stderr, "ExtabEntryExtract: bytecode can't be represented");
- break;
- case ExInvalid:
- fprintf(stderr, "ExtabEntryExtract: index table entry is invalid");
- break;
- default:
- fprintf(stderr, "ExtabEntryExtract: unknown error: %d", (int)res);
- break;
- }
- continue;
- }
-
- // Finally, work through the unwind instructions in |buf| and
- // create CFI entries that Breakpad can use. This can also fail.
- // First, add a new stack frame entry, into which ExtabEntryDecode
- // will write the CFI entries.
- if (!handler_->HasStackFrame(addr, next_addr - addr)) {
- handler_->AddStackFrame(addr, next_addr - addr);
- int ret = ExtabEntryDecode(buf, buf_used);
- if (ret < 0) {
- handler_->DeleteStackFrame();
- fprintf(stderr, "ExtabEntryDecode: failed with error code: %d", ret);
- continue;
- }
- handler_->SubmitStackFrame();
- }
-
- } /* iterating over .exidx */
-}
-
-} // namespace arm_ex_reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h
deleted file mode 100644
index 9b54e8a0b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_reader.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* libunwind - a platform-independent unwind library
- Copyright 2011 Linaro Limited
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-// 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.
-
-
-// Derived from libunwind, with extensive modifications.
-
-#ifndef COMMON_ARM_EX_READER_H__
-#define COMMON_ARM_EX_READER_H__
-
-#include "common/arm_ex_to_module.h"
-#include "common/memory_range.h"
-
-namespace arm_ex_reader {
-
-// This class is a reader for ARM unwind information
-// from .ARM.exidx and .ARM.extab sections.
-class ExceptionTableInfo {
- public:
- ExceptionTableInfo(const char* exidx, size_t exidx_size,
- const char* extab, size_t extab_size,
- uint32_t text_last_svma,
- arm_ex_to_module::ARMExToModule* handler,
- const char* mapping_addr,
- uint32_t loading_addr)
- : mr_exidx_(google_breakpad::MemoryRange(exidx, exidx_size)),
- mr_extab_(google_breakpad::MemoryRange(extab, extab_size)),
- text_last_svma_(text_last_svma),
- handler_(handler), mapping_addr_(mapping_addr),
- loading_addr_(loading_addr) { }
-
- ~ExceptionTableInfo() { }
-
- // Parses the entries in .ARM.exidx and possibly
- // in .ARM.extab tables, reports what we find to
- // arm_ex_to_module::ARMExToModule.
- void Start();
-
- private:
- google_breakpad::MemoryRange mr_exidx_;
- google_breakpad::MemoryRange mr_extab_;
- uint32_t text_last_svma_;
- arm_ex_to_module::ARMExToModule* handler_;
- const char* mapping_addr_;
- uint32_t loading_addr_;
-
- enum ExExtractResult {
- ExSuccess, // success
- ExInBufOverflow, // out-of-range while reading .exidx
- ExOutBufOverflow, // output buffer is too small
- ExCantUnwind, // this function is marked CANT_UNWIND
- ExCantRepresent, // entry valid, but we can't represent it
- ExInvalid // entry is invalid
- };
- ExExtractResult
- ExtabEntryExtract(const struct arm_ex_to_module::exidx_entry* entry,
- uint8_t* buf, size_t buf_size,
- size_t* buf_used);
-
- int ExtabEntryDecode(const uint8_t* buf, size_t buf_size);
-};
-
-} // namespace arm_ex_reader
-
-#endif // COMMON_ARM_EX_READER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
deleted file mode 100644
index c326744f6..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-
-/* libunwind - a platform-independent unwind library
- Copyright 2011 Linaro Limited
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-// 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.
-
-
-// Derived from libunwind, with extensive modifications.
-
-#include "common/arm_ex_to_module.h"
-
-#include <stdio.h>
-#include <assert.h>
-
-// For big-picture comments on how the EXIDX reader works,
-// see arm_ex_reader.cc.
-
-#define ARM_EXBUF_START(x) (((x) >> 4) & 0x0f)
-#define ARM_EXBUF_COUNT(x) ((x) & 0x0f)
-#define ARM_EXBUF_END(x) (ARM_EXBUF_START(x) + ARM_EXBUF_COUNT(x))
-
-using google_breakpad::Module;
-
-namespace arm_ex_to_module {
-
-static const char* const regnames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "fps", "cpsr"
-};
-
-// Translate command from extab_data to command for Module.
-int ARMExToModule::TranslateCmd(const struct extab_data* edata,
- Module::StackFrameEntry* entry, string& vsp) {
- int ret = 0;
- switch (edata->cmd) {
- case ARM_EXIDX_CMD_FINISH:
- /* Copy LR to PC if there isn't currently a rule for PC in force. */
- if (entry->initial_rules.find("pc")
- == entry->initial_rules.end()) {
- if (entry->initial_rules.find("lr")
- == entry->initial_rules.end()) {
- entry->initial_rules["pc"] = "lr";
- } else {
- entry->initial_rules["pc"] = entry->initial_rules["lr"];
- }
- }
- break;
- case ARM_EXIDX_CMD_SUB_FROM_VSP:
- {
- char c[16];
- sprintf(c, " %d -", edata->data);
- vsp += c;
- }
- break;
- case ARM_EXIDX_CMD_ADD_TO_VSP:
- {
- char c[16];
- sprintf(c, " %d +", edata->data);
- vsp += c;
- }
- break;
- case ARM_EXIDX_CMD_REG_POP:
- for (unsigned int i = 0; i < 16; i++) {
- if (edata->data & (1 << i)) {
- entry->initial_rules[regnames[i]]
- = vsp + " ^";
- vsp += " 4 +";
- }
- }
- /* Set cfa in case the SP got popped. */
- if (edata->data & (1 << 13)) {
- vsp = entry->initial_rules["sp"];
- }
- break;
- case ARM_EXIDX_CMD_REG_TO_SP: {
- assert (edata->data < 16);
- const char* const regname = regnames[edata->data];
- if (entry->initial_rules.find(regname) == entry->initial_rules.end()) {
- entry->initial_rules["sp"] = regname;
- } else {
- entry->initial_rules["sp"] = entry->initial_rules[regname];
- }
- vsp = entry->initial_rules["sp"];
- break;
- }
- case ARM_EXIDX_CMD_VFP_POP:
- /* Don't recover VFP registers, but be sure to adjust the stack
- pointer. */
- for (unsigned int i = ARM_EXBUF_START(edata->data);
- i <= ARM_EXBUF_END(edata->data); i++) {
- vsp += " 8 +";
- }
- if (!(edata->data & ARM_EXIDX_VFP_FSTMD)) {
- vsp += " 4 +";
- }
- break;
- case ARM_EXIDX_CMD_WREG_POP:
- for (unsigned int i = ARM_EXBUF_START(edata->data);
- i <= ARM_EXBUF_END(edata->data); i++) {
- vsp += " 8 +";
- }
- break;
- case ARM_EXIDX_CMD_WCGR_POP:
- // Pop wCGR registers under mask {wCGR3,2,1,0}, hence "i < 4"
- for (unsigned int i = 0; i < 4; i++) {
- if (edata->data & (1 << i)) {
- vsp += " 4 +";
- }
- }
- break;
- case ARM_EXIDX_CMD_REFUSED:
- case ARM_EXIDX_CMD_RESERVED:
- ret = -1;
- break;
- }
- return ret;
-}
-
-bool ARMExToModule::HasStackFrame(uintptr_t addr, size_t size) {
- // Invariant: the range [addr,covered) is covered by existing stack
- // frame entries.
- uintptr_t covered = addr;
- while (covered < addr + size) {
- const Module::StackFrameEntry *old_entry =
- module_->FindStackFrameEntryByAddress(covered);
- if (!old_entry) {
- return false;
- }
- covered = old_entry->address + old_entry->size;
- }
- return true;
-}
-
-void ARMExToModule::AddStackFrame(uintptr_t addr, size_t size) {
- stack_frame_entry_ = new Module::StackFrameEntry;
- stack_frame_entry_->address = addr;
- stack_frame_entry_->size = size;
- stack_frame_entry_->initial_rules[".cfa"] = "sp";
- vsp_ = "sp";
-}
-
-int ARMExToModule::ImproveStackFrame(const struct extab_data* edata) {
- return TranslateCmd(edata, stack_frame_entry_, vsp_) ;
-}
-
-void ARMExToModule::DeleteStackFrame() {
- delete stack_frame_entry_;
-}
-
-void ARMExToModule::SubmitStackFrame() {
- // return address always winds up in pc
- stack_frame_entry_->initial_rules[".ra"]
- = stack_frame_entry_->initial_rules["pc"];
- // the final value of vsp is the new value of sp
- stack_frame_entry_->initial_rules["sp"] = vsp_;
- module_->AddStackFrameEntry(stack_frame_entry_);
-}
-
-} // namespace arm_ex_to_module
diff --git a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
deleted file mode 100644
index f413a16a9..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/arm_ex_to_module.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* libunwind - a platform-independent unwind library
- Copyright 2011 Linaro Limited
-
-This file is part of libunwind.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-// 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.
-
-
-// Derived from libunwind, with extensive modifications.
-
-#ifndef COMMON_ARM_EX_TO_MODULE__
-#define COMMON_ARM_EX_TO_MODULE__
-
-#include "common/module.h"
-
-#include <string.h>
-
-namespace arm_ex_to_module {
-
-using google_breakpad::Module;
-
-typedef enum extab_cmd {
- ARM_EXIDX_CMD_FINISH,
- ARM_EXIDX_CMD_SUB_FROM_VSP,
- ARM_EXIDX_CMD_ADD_TO_VSP,
- ARM_EXIDX_CMD_REG_POP,
- ARM_EXIDX_CMD_REG_TO_SP,
- ARM_EXIDX_CMD_VFP_POP,
- ARM_EXIDX_CMD_WREG_POP,
- ARM_EXIDX_CMD_WCGR_POP,
- ARM_EXIDX_CMD_RESERVED,
- ARM_EXIDX_CMD_REFUSED,
-} extab_cmd_t;
-
-struct exidx_entry {
- uint32_t addr;
- uint32_t data;
-};
-
-struct extab_data {
- extab_cmd_t cmd;
- uint32_t data;
-};
-
-enum extab_cmd_flags {
- ARM_EXIDX_VFP_SHIFT_16 = 1 << 16,
- ARM_EXIDX_VFP_FSTMD = 1 << 17, // distinguishes FSTMxxD from FSTMxxX
-};
-
-// Receives information from arm_ex_reader::ExceptionTableInfo
-// and adds it to the Module object
-class ARMExToModule {
- public:
- ARMExToModule(Module* module)
- : module_(module) { }
- ~ARMExToModule() { }
- bool HasStackFrame(uintptr_t addr, size_t size);
- void AddStackFrame(uintptr_t addr, size_t size);
- int ImproveStackFrame(const struct extab_data* edata);
- void DeleteStackFrame();
- void SubmitStackFrame();
- private:
- Module* module_;
- Module::StackFrameEntry* stack_frame_entry_;
- string vsp_;
- int TranslateCmd(const struct extab_data* edata,
- Module::StackFrameEntry* entry,
- string& vsp);
-};
-
-} // namespace arm_ex_to_module
-
-#endif // COMMON_ARM_EX_TO_MODULE__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/basictypes.h b/toolkit/crashreporter/google-breakpad/src/common/basictypes.h
deleted file mode 100644
index 9426c1f6c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/basictypes.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 COMMON_BASICTYPES_H_
-#define COMMON_BASICTYPES_H_
-
-// A macro to disallow the copy constructor and operator= functions
-// This should be used in the private: declarations for a class
-#ifndef DISALLOW_COPY_AND_ASSIGN
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-#endif // DISALLOW_COPY_AND_ASSIGN
-
-namespace google_breakpad {
-
-// Used to explicitly mark the return value of a function as unused. If you are
-// really sure you don't want to do anything with the return value of a function
-// that has been marked with __attribute__((warn_unused_result)), wrap it with
-// this. Example:
-//
-// scoped_ptr<MyType> my_var = ...;
-// if (TakeOwnership(my_var.get()) == SUCCESS)
-// ignore_result(my_var.release());
-//
-template<typename T>
-inline void ignore_result(const T&) {
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_BASICTYPES_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/byte_cursor.h b/toolkit/crashreporter/google-breakpad/src/common/byte_cursor.h
deleted file mode 100644
index accd54e0a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/byte_cursor.h
+++ /dev/null
@@ -1,265 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// byte_cursor.h: Classes for parsing values from a buffer of bytes.
-// The ByteCursor class provides a convenient interface for reading
-// fixed-size integers of arbitrary endianness, being thorough about
-// checking for buffer overruns.
-
-#ifndef COMMON_BYTE_CURSOR_H_
-#define COMMON_BYTE_CURSOR_H_
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-// A buffer holding a series of bytes.
-struct ByteBuffer {
- ByteBuffer() : start(0), end(0) { }
- ByteBuffer(const uint8_t *set_start, size_t set_size)
- : start(set_start), end(set_start + set_size) { }
- ~ByteBuffer() { };
-
- // Equality operators. Useful in unit tests, and when we're using
- // ByteBuffers to refer to regions of a larger buffer.
- bool operator==(const ByteBuffer &that) const {
- return start == that.start && end == that.end;
- }
- bool operator!=(const ByteBuffer &that) const {
- return start != that.start || end != that.end;
- }
-
- // Not C++ style guide compliant, but this definitely belongs here.
- size_t Size() const {
- assert(start <= end);
- return end - start;
- }
-
- const uint8_t *start, *end;
-};
-
-// A cursor pointing into a ByteBuffer that can parse numbers of various
-// widths and representations, strings, and data blocks, advancing through
-// the buffer as it goes. All ByteCursor operations check that accesses
-// haven't gone beyond the end of the enclosing ByteBuffer.
-class ByteCursor {
- public:
- // Create a cursor reading bytes from the start of BUFFER. By default, the
- // cursor reads multi-byte values in little-endian form.
- ByteCursor(const ByteBuffer *buffer, bool big_endian = false)
- : buffer_(buffer), here_(buffer->start),
- big_endian_(big_endian), complete_(true) { }
-
- // Accessor and setter for this cursor's endianness flag.
- bool big_endian() const { return big_endian_; }
- void set_big_endian(bool big_endian) { big_endian_ = big_endian; }
-
- // Accessor and setter for this cursor's current position. The setter
- // returns a reference to this cursor.
- const uint8_t *here() const { return here_; }
- ByteCursor &set_here(const uint8_t *here) {
- assert(buffer_->start <= here && here <= buffer_->end);
- here_ = here;
- return *this;
- }
-
- // Return the number of bytes available to read at the cursor.
- size_t Available() const { return size_t(buffer_->end - here_); }
-
- // Return true if this cursor is at the end of its buffer.
- bool AtEnd() const { return Available() == 0; }
-
- // When used as a boolean value this cursor converts to true if all
- // prior reads have been completed, or false if we ran off the end
- // of the buffer.
- operator bool() const { return complete_; }
-
- // Read a SIZE-byte integer at this cursor, signed if IS_SIGNED is true,
- // unsigned otherwise, using the cursor's established endianness, and set
- // *RESULT to the number. If we read off the end of our buffer, clear
- // this cursor's complete_ flag, and store a dummy value in *RESULT.
- // Return a reference to this cursor.
- template<typename T>
- ByteCursor &Read(size_t size, bool is_signed, T *result) {
- if (CheckAvailable(size)) {
- T v = 0;
- if (big_endian_) {
- for (size_t i = 0; i < size; i++)
- v = (v << 8) + here_[i];
- } else {
- // This loop condition looks weird, but size_t is unsigned, so
- // decrementing i after it is zero yields the largest size_t value.
- for (size_t i = size - 1; i < size; i--)
- v = (v << 8) + here_[i];
- }
- if (is_signed && size < sizeof(T)) {
- size_t sign_bit = (T)1 << (size * 8 - 1);
- v = (v ^ sign_bit) - sign_bit;
- }
- here_ += size;
- *result = v;
- } else {
- *result = (T) 0xdeadbeef;
- }
- return *this;
- }
-
- // Read an integer, using the cursor's established endianness and
- // *RESULT's size and signedness, and set *RESULT to the number. If we
- // read off the end of our buffer, clear this cursor's complete_ flag.
- // Return a reference to this cursor.
- template<typename T>
- ByteCursor &operator>>(T &result) {
- bool T_is_signed = (T)-1 < 0;
- return Read(sizeof(T), T_is_signed, &result);
- }
-
- // Copy the SIZE bytes at the cursor to BUFFER, and advance this
- // cursor to the end of them. If we read off the end of our buffer,
- // clear this cursor's complete_ flag, and set *POINTER to NULL.
- // Return a reference to this cursor.
- ByteCursor &Read(uint8_t *buffer, size_t size) {
- if (CheckAvailable(size)) {
- memcpy(buffer, here_, size);
- here_ += size;
- }
- return *this;
- }
-
- // Set STR to a copy of the '\0'-terminated string at the cursor. If the
- // byte buffer does not contain a terminating zero, clear this cursor's
- // complete_ flag, and set STR to the empty string. Return a reference to
- // this cursor.
- ByteCursor &CString(string *str) {
- const uint8_t *end
- = static_cast<const uint8_t *>(memchr(here_, '\0', Available()));
- if (end) {
- str->assign(reinterpret_cast<const char *>(here_), end - here_);
- here_ = end + 1;
- } else {
- str->clear();
- here_ = buffer_->end;
- complete_ = false;
- }
- return *this;
- }
-
- // Like CString(STR), but extract the string from a fixed-width buffer
- // LIMIT bytes long, which may or may not contain a terminating '\0'
- // byte. Specifically:
- //
- // - If there are not LIMIT bytes available at the cursor, clear the
- // cursor's complete_ flag and set STR to the empty string.
- //
- // - Otherwise, if the LIMIT bytes at the cursor contain any '\0'
- // characters, set *STR to a copy of the bytes before the first '\0',
- // and advance the cursor by LIMIT bytes.
- //
- // - Otherwise, set *STR to a copy of those LIMIT bytes, and advance the
- // cursor by LIMIT bytes.
- ByteCursor &CString(string *str, size_t limit) {
- if (CheckAvailable(limit)) {
- const uint8_t *end
- = static_cast<const uint8_t *>(memchr(here_, '\0', limit));
- if (end)
- str->assign(reinterpret_cast<const char *>(here_), end - here_);
- else
- str->assign(reinterpret_cast<const char *>(here_), limit);
- here_ += limit;
- } else {
- str->clear();
- }
- return *this;
- }
-
- // Set *POINTER to point to the SIZE bytes at the cursor, and advance
- // this cursor to the end of them. If SIZE is omitted, don't move the
- // cursor. If we read off the end of our buffer, clear this cursor's
- // complete_ flag, and set *POINTER to NULL. Return a reference to this
- // cursor.
- ByteCursor &PointTo(const uint8_t **pointer, size_t size = 0) {
- if (CheckAvailable(size)) {
- *pointer = here_;
- here_ += size;
- } else {
- *pointer = NULL;
- }
- return *this;
- }
-
- // Skip SIZE bytes at the cursor. If doing so would advance us off
- // the end of our buffer, clear this cursor's complete_ flag, and
- // set *POINTER to NULL. Return a reference to this cursor.
- ByteCursor &Skip(size_t size) {
- if (CheckAvailable(size))
- here_ += size;
- return *this;
- }
-
- private:
- // If there are at least SIZE bytes available to read from the buffer,
- // return true. Otherwise, set here_ to the end of the buffer, set
- // complete_ to false, and return false.
- bool CheckAvailable(size_t size) {
- if (Available() >= size) {
- return true;
- } else {
- here_ = buffer_->end;
- complete_ = false;
- return false;
- }
- }
-
- // The buffer we're reading bytes from.
- const ByteBuffer *buffer_;
-
- // The next byte within buffer_ that we'll read.
- const uint8_t *here_;
-
- // True if we should read numbers in big-endian form; false if we
- // should read in little-endian form.
- bool big_endian_;
-
- // True if we've been able to read all we've been asked to.
- bool complete_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_BYTE_CURSOR_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/byte_cursor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/byte_cursor_unittest.cc
deleted file mode 100644
index 06bfd89d7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/byte_cursor_unittest.cc
+++ /dev/null
@@ -1,776 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// byte_cursor_unittest.cc: Unit tests for google_breakpad::ByteBuffer
-// and google_breakpad::ByteCursor.
-
-#include <string>
-
-#include <string.h>
-
-#include "breakpad_googletest_includes.h"
-#include "common/byte_cursor.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::ByteBuffer;
-using google_breakpad::ByteCursor;
-
-TEST(Buffer, SizeOfNothing) {
- uint8_t data[1];
- ByteBuffer buffer(data, 0);
- EXPECT_EQ(0U, buffer.Size());
-}
-
-TEST(Buffer, SizeOfSomething) {
- uint8_t data[10];
- ByteBuffer buffer(data, sizeof(data));
- EXPECT_EQ(10U, buffer.Size());
-}
-
-TEST(Extent, AvailableEmpty) {
- uint8_t data[1];
- ByteBuffer buffer(data, 0);
- ByteCursor cursor(&buffer);
- EXPECT_EQ(0U, cursor.Available());
-}
-
-TEST(Extent, AtEndEmpty) {
- uint8_t data[1];
- ByteBuffer buffer(data, 0);
- ByteCursor cursor(&buffer);
- EXPECT_TRUE(cursor.AtEnd());
-}
-
-TEST(Extent, AsBoolEmpty) {
- uint8_t data[1];
- ByteBuffer buffer(data, 0);
- ByteCursor cursor(&buffer);
- EXPECT_TRUE(cursor);
-}
-
-TEST(Extent, AvailableSome) {
- uint8_t data[10];
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- EXPECT_EQ(10U, cursor.Available());
-}
-
-TEST(Extent, AtEndSome) {
- uint8_t data[10];
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- EXPECT_FALSE(cursor.AtEnd());
- EXPECT_TRUE(cursor.Skip(sizeof(data)).AtEnd());
-}
-
-TEST(Extent, AsBoolSome) {
- uint8_t data[10];
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- EXPECT_TRUE(cursor);
- EXPECT_TRUE(cursor.Skip(sizeof(data)));
- EXPECT_FALSE(cursor.Skip(1));
-}
-
-TEST(Extent, Cursor) {
- uint8_t data[] = { 0xf7,
- 0x9f, 0xbe,
- 0x67, 0xfb, 0xd3, 0x58,
- 0x6f, 0x36, 0xde, 0xd1,
- 0x2a, 0x2a, 0x2a };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
-
- uint8_t a;
- uint16_t b;
- uint32_t c;
- uint32_t d;
- uint8_t stars[3];
-
- EXPECT_EQ(data + 0U, cursor.here());
-
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(data + 1U, cursor.here());
-
- EXPECT_TRUE(cursor >> b);
- EXPECT_EQ(data + 3U, cursor.here());
-
- EXPECT_TRUE(cursor >> c);
- EXPECT_EQ(data + 7U, cursor.here());
-
- EXPECT_TRUE(cursor.Skip(4));
- EXPECT_EQ(data + 11U, cursor.here());
-
- EXPECT_TRUE(cursor.Read(stars, 3));
- EXPECT_EQ(data + 14U, cursor.here());
-
- EXPECT_FALSE(cursor >> d);
- EXPECT_EQ(data + 14U, cursor.here());
-}
-
-TEST(Extent, SetOffset) {
- uint8_t data[] = { 0x5c, 0x79, 0x8c, 0xd5 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
-
- uint8_t a, b, c, d, e;
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(0x5cU, a);
- EXPECT_EQ(data + 1U, cursor.here());
- EXPECT_TRUE(((cursor >> b).set_here(data + 3) >> c).set_here(data + 1)
- >> d >> e);
- EXPECT_EQ(0x79U, b);
- EXPECT_EQ(0xd5U, c);
- EXPECT_EQ(0x79U, d);
- EXPECT_EQ(0x8cU, e);
- EXPECT_EQ(data + 3U, cursor.here());
-}
-
-TEST(BigEndian, Signed1) {
- uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- cursor.set_big_endian(true);
- int a, b, c, d, e;
- ASSERT_TRUE(cursor
- .Read(1, true, &a)
- .Read(1, true, &b)
- .Read(1, true, &c)
- .Read(1, true, &d));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7f, b);
- EXPECT_EQ(-0x80, c);
- EXPECT_EQ(-1, d);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(1, true, &e));
-}
-
-TEST(BigEndian, Signed2) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x80, 0x7f, 0xff,
- 0x80, 0x00, 0x80, 0x80, 0xff, 0xff,
- 0x39, 0xf1, 0x8a, 0xbc, 0x5a, 0xec };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, true);
- int a, b, c, d, e, f, g, h, i, j;
- ASSERT_TRUE(cursor
- .Read(2, true, &a)
- .Read(2, true, &b)
- .Read(2, true, &c)
- .Read(2, true, &d)
- .Read(2, true, &e)
- .Read(2, true, &f)
- .Read(2, true, &g)
- .Read(2, true, &h)
- .Read(2, true, &i));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x80, b);
- EXPECT_EQ(0x7fff, c);
- EXPECT_EQ(-0x8000, d);
- EXPECT_EQ(-0x7f80, e);
- EXPECT_EQ(-1, f);
- EXPECT_EQ(0x39f1, g);
- EXPECT_EQ(-0x7544, h);
- EXPECT_EQ(0x5aec, i);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(2, true, &j));
-}
-
-TEST(BigEndian, Signed4) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xff, 0xff, 0xff,
- 0x80, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff,
- 0xb6, 0xb1, 0xff, 0xef,
- 0x19, 0x6a, 0xca, 0x46 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- cursor.set_big_endian(true);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(4, true, &a)
- .Read(4, true, &b)
- .Read(4, true, &c)
- .Read(4, true, &d)
- .Read(4, true, &e)
- .Read(4, true, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffff, b);
- EXPECT_EQ(-0x80000000LL, c);
- EXPECT_EQ(-1, d);
- EXPECT_EQ((int32_t) 0xb6b1ffef, e);
- EXPECT_EQ(0x196aca46, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(4, true, &g));
-}
-
-TEST(BigEndian, Signed8) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x93, 0x20, 0xd5, 0xe9, 0xd2, 0xd5, 0x87, 0x9c,
- 0x4e, 0x42, 0x49, 0xd2, 0x7f, 0x84, 0x14, 0xa4 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, true);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(8, true, &a)
- .Read(8, true, &b)
- .Read(8, true, &c)
- .Read(8, true, &d)
- .Read(8, true, &e)
- .Read(8, true, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffffffffffffLL, b);
- EXPECT_EQ(-0x7fffffffffffffffLL - 1, c);
- EXPECT_EQ(-1, d);
- EXPECT_EQ((int64_t) 0x9320d5e9d2d5879cULL, e);
- EXPECT_EQ(0x4e4249d27f8414a4LL, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(8, true, &g));
-}
-
-TEST(BigEndian, Unsigned1) {
- uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- cursor.set_big_endian(true);
- int32_t a, b, c, d, e;
- ASSERT_TRUE(cursor
- .Read(1, false, &a)
- .Read(1, false, &b)
- .Read(1, false, &c)
- .Read(1, false, &d));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7f, b);
- EXPECT_EQ(0x80, c);
- EXPECT_EQ(0xff, d);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(1, false, &e));
-}
-
-TEST(BigEndian, Unsigned2) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x80, 0x7f, 0xff,
- 0x80, 0x00, 0x80, 0x80, 0xff, 0xff,
- 0x39, 0xf1, 0x8a, 0xbc, 0x5a, 0xec };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, true);
- int64_t a, b, c, d, e, f, g, h, i, j;
- ASSERT_TRUE(cursor
- .Read(2, false, &a)
- .Read(2, false, &b)
- .Read(2, false, &c)
- .Read(2, false, &d)
- .Read(2, false, &e)
- .Read(2, false, &f)
- .Read(2, false, &g)
- .Read(2, false, &h)
- .Read(2, false, &i));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x80, b);
- EXPECT_EQ(0x7fff, c);
- EXPECT_EQ(0x8000, d);
- EXPECT_EQ(0x8080, e);
- EXPECT_EQ(0xffff, f);
- EXPECT_EQ(0x39f1, g);
- EXPECT_EQ(0x8abc, h);
- EXPECT_EQ(0x5aec, i);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(2, false, &j));
-}
-
-TEST(BigEndian, Unsigned4) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xff, 0xff, 0xff,
- 0x80, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff,
- 0xb6, 0xb1, 0xff, 0xef,
- 0x19, 0x6a, 0xca, 0x46 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- cursor.set_big_endian(true);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(4, false, &a)
- .Read(4, false, &b)
- .Read(4, false, &c)
- .Read(4, false, &d)
- .Read(4, false, &e)
- .Read(4, false, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffff, b);
- EXPECT_EQ(0x80000000, c);
- EXPECT_EQ(0xffffffff, d);
- EXPECT_EQ(0xb6b1ffef, e);
- EXPECT_EQ(0x196aca46, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(4, false, &g));
-}
-
-TEST(BigEndian, Unsigned8) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x93, 0x20, 0xd5, 0xe9, 0xd2, 0xd5, 0x87, 0x9c,
- 0x4e, 0x42, 0x49, 0xd2, 0x7f, 0x84, 0x14, 0xa4 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, true);
- uint64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(8, false, &a)
- .Read(8, false, &b)
- .Read(8, false, &c)
- .Read(8, false, &d)
- .Read(8, false, &e)
- .Read(8, false, &f));
- EXPECT_EQ(0U, a);
- EXPECT_EQ(0x7fffffffffffffffULL, b);
- EXPECT_EQ(0x8000000000000000ULL, c);
- EXPECT_EQ(0xffffffffffffffffULL, d);
- EXPECT_EQ(0x9320d5e9d2d5879cULL, e);
- EXPECT_EQ(0x4e4249d27f8414a4ULL, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(8, false, &g));
-}
-
-TEST(LittleEndian, Signed1) {
- uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int32_t a, b, c, d, e;
- ASSERT_TRUE(cursor
- .Read(1, true, &a)
- .Read(1, true, &b)
- .Read(1, true, &c)
- .Read(1, true, &d));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7f, b);
- EXPECT_EQ(-0x80, c);
- EXPECT_EQ(-1, d);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(1, true, &e));
-}
-
-TEST(LittleEndian, Signed2) {
- uint8_t data[] = { 0x00, 0x00, 0x80, 0x00, 0xff, 0x7f,
- 0x00, 0x80, 0x80, 0x80, 0xff, 0xff,
- 0xf1, 0x39, 0xbc, 0x8a, 0xec, 0x5a };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, false);
- int32_t a, b, c, d, e, f, g, h, i, j;
- ASSERT_TRUE(cursor
- .Read(2, true, &a)
- .Read(2, true, &b)
- .Read(2, true, &c)
- .Read(2, true, &d)
- .Read(2, true, &e)
- .Read(2, true, &f)
- .Read(2, true, &g)
- .Read(2, true, &h)
- .Read(2, true, &i));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x80, b);
- EXPECT_EQ(0x7fff, c);
- EXPECT_EQ(-0x8000, d);
- EXPECT_EQ(-0x7f80, e);
- EXPECT_EQ(-1, f);
- EXPECT_EQ(0x39f1, g);
- EXPECT_EQ(-0x7544, h);
- EXPECT_EQ(0x5aec, i);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(2, true, &j));
-}
-
-TEST(LittleEndian, Signed4) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0x7f,
- 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff,
- 0xef, 0xff, 0xb1, 0xb6,
- 0x46, 0xca, 0x6a, 0x19 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(4, true, &a)
- .Read(4, true, &b)
- .Read(4, true, &c)
- .Read(4, true, &d)
- .Read(4, true, &e)
- .Read(4, true, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffff, b);
- EXPECT_EQ(-0x80000000LL, c);
- EXPECT_EQ(-1, d);
- EXPECT_EQ((int32_t) 0xb6b1ffef, e);
- EXPECT_EQ(0x196aca46, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(4, true, &g));
-}
-
-TEST(LittleEndian, Signed8) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x9c, 0x87, 0xd5, 0xd2, 0xe9, 0xd5, 0x20, 0x93,
- 0xa4, 0x14, 0x84, 0x7f, 0xd2, 0x49, 0x42, 0x4e };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer, false);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(8, true, &a)
- .Read(8, true, &b)
- .Read(8, true, &c)
- .Read(8, true, &d)
- .Read(8, true, &e)
- .Read(8, true, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffffffffffffLL, b);
- EXPECT_EQ(-0x7fffffffffffffffLL - 1, c);
- EXPECT_EQ(-1, d);
- EXPECT_EQ((int64_t) 0x9320d5e9d2d5879cULL, e);
- EXPECT_EQ(0x4e4249d27f8414a4LL, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(8, true, &g));
-}
-
-TEST(LittleEndian, Unsigned1) {
- uint8_t data[] = { 0x00, 0x7f, 0x80, 0xff };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int32_t a, b, c, d, e;
- ASSERT_TRUE(cursor
- .Read(1, false, &a)
- .Read(1, false, &b)
- .Read(1, false, &c)
- .Read(1, false, &d));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7f, b);
- EXPECT_EQ(0x80, c);
- EXPECT_EQ(0xff, d);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(1, false, &e));
-}
-
-TEST(LittleEndian, Unsigned2) {
- uint8_t data[] = { 0x00, 0x00, 0x80, 0x00, 0xff, 0x7f,
- 0x00, 0x80, 0x80, 0x80, 0xff, 0xff,
- 0xf1, 0x39, 0xbc, 0x8a, 0xec, 0x5a };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int32_t a, b, c, d, e, f, g, h, i, j;
- ASSERT_TRUE(cursor
- .Read(2, false, &a)
- .Read(2, false, &b)
- .Read(2, false, &c)
- .Read(2, false, &d)
- .Read(2, false, &e)
- .Read(2, false, &f)
- .Read(2, false, &g)
- .Read(2, false, &h)
- .Read(2, false, &i));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x80, b);
- EXPECT_EQ(0x7fff, c);
- EXPECT_EQ(0x8000, d);
- EXPECT_EQ(0x8080, e);
- EXPECT_EQ(0xffff, f);
- EXPECT_EQ(0x39f1, g);
- EXPECT_EQ(0x8abc, h);
- EXPECT_EQ(0x5aec, i);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(2, false, &j));
-}
-
-TEST(LittleEndian, Unsigned4) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0x7f,
- 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff,
- 0xef, 0xff, 0xb1, 0xb6,
- 0x46, 0xca, 0x6a, 0x19 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(4, false, &a)
- .Read(4, false, &b)
- .Read(4, false, &c)
- .Read(4, false, &d)
- .Read(4, false, &e)
- .Read(4, false, &f));
- EXPECT_EQ(0, a);
- EXPECT_EQ(0x7fffffff, b);
- EXPECT_EQ(0x80000000, c);
- EXPECT_EQ(0xffffffff, d);
- EXPECT_EQ(0xb6b1ffef, e);
- EXPECT_EQ(0x196aca46, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(4, false, &g));
-}
-
-TEST(LittleEndian, Unsigned8) {
- uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x9c, 0x87, 0xd5, 0xd2, 0xe9, 0xd5, 0x20, 0x93,
- 0xa4, 0x14, 0x84, 0x7f, 0xd2, 0x49, 0x42, 0x4e };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- uint64_t a, b, c, d, e, f, g;
- ASSERT_TRUE(cursor
- .Read(8, false, &a)
- .Read(8, false, &b)
- .Read(8, false, &c)
- .Read(8, false, &d)
- .Read(8, false, &e)
- .Read(8, false, &f));
- EXPECT_EQ(0U, a);
- EXPECT_EQ(0x7fffffffffffffffULL, b);
- EXPECT_EQ(0x8000000000000000ULL, c);
- EXPECT_EQ(0xffffffffffffffffULL, d);
- EXPECT_EQ(0x9320d5e9d2d5879cULL, e);
- EXPECT_EQ(0x4e4249d27f8414a4ULL, f);
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor.Read(8, false, &g));
-}
-
-TEST(Extractor, Signed1) {
- uint8_t data[] = { 0xfd };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int8_t a;
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(-3, a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Signed2) {
- uint8_t data[] = { 0x13, 0xcd };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int16_t a;
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(-13037, a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Signed4) {
- uint8_t data[] = { 0xd2, 0xe4, 0x53, 0xe9 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- int32_t a;
- // For some reason, G++ 4.4.1 complains:
- // warning: array subscript is above array bounds
- // in ByteCursor::Read(size_t, bool, T *) as it inlines this call, but
- // I'm not able to see how such a reference would occur.
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(-380377902, a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Unsigned1) {
- uint8_t data[] = { 0xfd };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- uint8_t a;
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(0xfd, a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Unsigned2) {
- uint8_t data[] = { 0x13, 0xcd };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- uint16_t a;
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(0xcd13, a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Unsigned4) {
- uint8_t data[] = { 0xd2, 0xe4, 0x53, 0xe9 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- uint32_t a;
- // For some reason, G++ 4.4.1 complains:
- // warning: array subscript is above array bounds
- // in ByteCursor::Read(size_t, bool, T *) as it inlines this call, but
- // I'm not able to see how such a reference would occur.
- EXPECT_TRUE(cursor >> a);
- EXPECT_EQ(0xe953e4d2, a);
- EXPECT_FALSE(cursor >> a);
- EXPECT_FALSE(cursor >> a);
-}
-
-TEST(Extractor, Mixed) {
- uint8_t data[] = { 0x42,
- 0x25, 0x0b,
- 0x3d, 0x25, 0xed, 0x2a,
- 0xec, 0x16, 0x9e, 0x14, 0x61, 0x5b, 0x2c, 0xcf,
- 0xd8,
- 0x22, 0xa5,
- 0x3a, 0x02, 0x6a, 0xd7,
- 0x93, 0x2a, 0x2d, 0x8d, 0xb4, 0x95, 0xe0, 0xc6 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
- cursor.set_big_endian(true);
-
- uint8_t a;
- uint16_t b;
- uint32_t c;
- uint64_t d;
- int8_t e;
- int16_t f;
- int32_t g;
- int64_t h;
- int z;
- EXPECT_FALSE(cursor.AtEnd());
- EXPECT_TRUE(cursor >> a >> b >> c >> d >> e >> f >> g >> h);
- EXPECT_EQ(0x42U, a);
- EXPECT_EQ(0x250bU, b);
- EXPECT_EQ(0x3d25ed2aU, c);
- EXPECT_EQ(0xec169e14615b2ccfULL, d);
- EXPECT_EQ(-40, e);
- EXPECT_EQ(0x22a5, f);
- EXPECT_EQ(0x3a026ad7, g);
- EXPECT_EQ(-7842405714468937530LL, h);
-
- EXPECT_TRUE(cursor.AtEnd());
- EXPECT_FALSE(cursor >> z);
-}
-
-TEST(Strings, Zero) {
- uint8_t data[] = { 0xa6 };
- ByteBuffer buffer(data, 0);
- ByteCursor cursor(&buffer);
-
- uint8_t received[1];
- received[0] = 0xc2;
- EXPECT_TRUE(cursor.Read(received, 0));
- EXPECT_EQ(0xc2U, received[0]);
-}
-
-TEST(Strings, Some) {
- uint8_t data[] = { 0x5d, 0x31, 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xbb };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
-
- uint8_t received[7] = { 0xa7, 0xf7, 0x43, 0x0c, 0x27, 0xea, 0xed };
- EXPECT_TRUE(cursor.Skip(2).Read(received, 5));
- uint8_t expected[7] = { 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xea, 0xed };
- EXPECT_TRUE(memcmp(received, expected, 7) == 0);
-}
-
-TEST(Strings, TooMuch) {
- uint8_t data[] = { 0x5d, 0x31, 0x09, 0xa6, 0x2e, 0x2c, 0x83, 0xbb };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
-
- uint8_t received1[3];
- uint8_t received2[3];
- uint8_t received3[3];
- EXPECT_FALSE(cursor
- .Read(received1, 3)
- .Read(received2, 3)
- .Read(received3, 3));
- uint8_t expected1[3] = { 0x5d, 0x31, 0x09 };
- uint8_t expected2[3] = { 0xa6, 0x2e, 0x2c };
-
- EXPECT_TRUE(memcmp(received1, expected1, 3) == 0);
- EXPECT_TRUE(memcmp(received2, expected2, 3) == 0);
-}
-
-TEST(Strings, PointTo) {
- uint8_t data[] = { 0x83, 0x80, 0xb4, 0x38, 0x00, 0x2c, 0x0a, 0x27 };
- ByteBuffer buffer(data, sizeof(data));
- ByteCursor cursor(&buffer);
-
- const uint8_t *received1;
- const uint8_t *received2;
- const uint8_t *received3;
- const uint8_t *received4;
- EXPECT_FALSE(cursor
- .PointTo(&received1, 3)
- .PointTo(&received2, 3)
- .PointTo(&received3)
- .PointTo(&received4, 3));
- EXPECT_EQ(data + 0, received1);
- EXPECT_EQ(data + 3, received2);
- EXPECT_EQ(data + 6, received3);
- EXPECT_EQ(NULL, received4);
-}
-
-TEST(Strings, CString) {
- uint8_t data[] = "abc\0\0foo";
- ByteBuffer buffer(data, sizeof(data) - 1); // don't include terminating '\0'
- ByteCursor cursor(&buffer);
-
- string a, b, c;
- EXPECT_TRUE(cursor.CString(&a).CString(&b));
- EXPECT_EQ("abc", a);
- EXPECT_EQ("", b);
- EXPECT_FALSE(cursor.CString(&c));
- EXPECT_EQ("", c);
- EXPECT_TRUE(cursor.AtEnd());
-}
-
-TEST(Strings, CStringLimit) {
- uint8_t data[] = "abcdef\0\0foobar";
- ByteBuffer buffer(data, sizeof(data) - 1); // don't include terminating '\0'
- ByteCursor cursor(&buffer);
-
- string a, b, c, d, e;
-
- EXPECT_TRUE(cursor.CString(&a, 3));
- EXPECT_EQ("abc", a);
-
- EXPECT_TRUE(cursor.CString(&b, 0));
- EXPECT_EQ("", b);
-
- EXPECT_TRUE(cursor.CString(&c, 6));
- EXPECT_EQ("def", c);
-
- EXPECT_TRUE(cursor.CString(&d, 4));
- EXPECT_EQ("ooba", d);
-
- EXPECT_FALSE(cursor.CString(&e, 4));
- EXPECT_EQ("", e);
-
- EXPECT_TRUE(cursor.AtEnd());
-}
-
-// uint8_t data[] = { 0xa6, 0x54, 0xdf, 0x67, 0x51, 0x43, 0xac, 0xf1 };
-// ByteBuffer buffer(data, sizeof(data));
diff --git a/toolkit/crashreporter/google-breakpad/src/common/common.gyp b/toolkit/crashreporter/google-breakpad/src/common/common.gyp
deleted file mode 100644
index 08772bf75..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/common.gyp
+++ /dev/null
@@ -1,250 +0,0 @@
-# Copyright 2014 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.
-
-{
- 'target_defaults': {
- 'target_conditions': [
- ['OS=="mac"', {
- 'defines': ['HAVE_MACH_O_NLIST_H'],
- }],
- ['OS=="linux"', {
- 'defines': ['HAVE_A_OUT_H'],
- }],
- ['OS!="android"', {'sources/': [['exclude', '(^|/)android/']]}],
- ['OS!="linux"', {'sources/': [['exclude', '(^|/)linux/']]}],
- ['OS!="mac"', {'sources/': [['exclude', '(^|/)mac/']]}],
- ['OS!="solaris"', {'sources/': [['exclude', '(^|/)solaris/']]}],
- ['OS!="win"', {'sources/': [['exclude', '(^|/)windows/']]}],
- ],
- },
- 'targets': [
- {
- 'target_name': 'common',
- 'type': 'static_library',
- 'sources': [
- 'android/breakpad_getcontext.S',
- 'android/include/elf.h',
- 'android/include/link.h',
- 'android/include/sgidefs.h',
- 'android/include/stab.h',
- 'android/include/sys/procfs.h',
- 'android/include/sys/signal.h',
- 'android/include/sys/user.h',
- 'android/include/ucontext.h',
- 'android/testing/include/wchar.h',
- 'android/testing/mkdtemp.h',
- 'android/testing/pthread_fixes.h',
- 'android/ucontext_constants.h',
- 'basictypes.h',
- 'byte_cursor.h',
- 'convert_UTF.c',
- 'convert_UTF.h',
- 'dwarf/bytereader-inl.h',
- 'dwarf/bytereader.cc',
- 'dwarf/bytereader.h',
- 'dwarf/cfi_assembler.cc',
- 'dwarf/cfi_assembler.h',
- 'dwarf/dwarf2diehandler.cc',
- 'dwarf/dwarf2diehandler.h',
- 'dwarf/dwarf2enums.h',
- 'dwarf/dwarf2reader.cc',
- 'dwarf/dwarf2reader.h',
- 'dwarf/dwarf2reader_test_common.h',
- 'dwarf/elf_reader.cc',
- 'dwarf/elf_reader.h',
- 'dwarf/functioninfo.cc',
- 'dwarf/functioninfo.h',
- 'dwarf/line_state_machine.h',
- 'dwarf/types.h',
- 'dwarf_cfi_to_module.cc',
- 'dwarf_cfi_to_module.h',
- 'dwarf_cu_to_module.cc',
- 'dwarf_cu_to_module.h',
- 'dwarf_line_to_module.cc',
- 'dwarf_line_to_module.h',
- 'language.cc',
- 'language.h',
- 'linux/crc32.cc',
- 'linux/crc32.h',
- 'linux/dump_symbols.cc',
- 'linux/dump_symbols.h',
- 'linux/eintr_wrapper.h',
- 'linux/elf_core_dump.cc',
- 'linux/elf_core_dump.h',
- 'linux/elf_gnu_compat.h',
- 'linux/elf_symbols_to_module.cc',
- 'linux/elf_symbols_to_module.h',
- 'linux/elfutils-inl.h',
- 'linux/elfutils.cc',
- 'linux/elfutils.h',
- 'linux/file_id.cc',
- 'linux/file_id.h',
- 'linux/google_crashdump_uploader.cc',
- 'linux/google_crashdump_uploader.h',
- 'linux/guid_creator.cc',
- 'linux/guid_creator.h',
- 'linux/http_upload.cc',
- 'linux/http_upload.h',
- 'linux/ignore_ret.h',
- 'linux/libcurl_wrapper.cc',
- 'linux/libcurl_wrapper.h',
- 'linux/linux_libc_support.cc',
- 'linux/linux_libc_support.h',
- 'linux/memory_mapped_file.cc',
- 'linux/memory_mapped_file.h',
- 'linux/safe_readlink.cc',
- 'linux/safe_readlink.h',
- 'linux/synth_elf.cc',
- 'linux/synth_elf.h',
- 'mac/arch_utilities.cc',
- 'mac/arch_utilities.h',
- 'mac/bootstrap_compat.cc',
- 'mac/bootstrap_compat.h',
- 'mac/byteswap.h',
- 'mac/dump_syms.h',
- 'mac/dump_syms.cc',
- 'mac/file_id.cc',
- 'mac/file_id.h',
- 'mac/GTMDefines.h',
- 'mac/GTMLogger.h',
- 'mac/GTMLogger.m',
- 'mac/HTTPMultipartUpload.h',
- 'mac/HTTPMultipartUpload.m',
- 'mac/MachIPC.h',
- 'mac/MachIPC.mm',
- 'mac/macho_id.cc',
- 'mac/macho_id.h',
- 'mac/macho_reader.cc',
- 'mac/macho_reader.h',
- 'mac/macho_utilities.cc',
- 'mac/macho_utilities.h',
- 'mac/macho_walker.cc',
- 'mac/macho_walker.h',
- 'mac/scoped_task_suspend-inl.h',
- 'mac/string_utilities.cc',
- 'mac/string_utilities.h',
- 'mac/super_fat_arch.h',
- 'md5.cc',
- 'md5.h',
- 'memory.h',
- 'memory_range.h',
- 'module.cc',
- 'module.h',
- 'scoped_ptr.h',
- 'simple_string_dictionary.cc',
- 'simple_string_dictionary.h',
- 'solaris/dump_symbols.cc',
- 'solaris/dump_symbols.h',
- 'solaris/file_id.cc',
- 'solaris/file_id.h',
- 'solaris/guid_creator.cc',
- 'solaris/guid_creator.h',
- 'solaris/message_output.h',
- 'stabs_reader.cc',
- 'stabs_reader.h',
- 'stabs_to_module.cc',
- 'stabs_to_module.h',
- 'string_conversion.cc',
- 'string_conversion.h',
- 'symbol_data.h',
- 'test_assembler.cc',
- 'test_assembler.h',
- 'unordered.h',
- 'using_std_string.h',
- 'windows/common_windows.gyp',
- 'windows/dia_util.cc',
- 'windows/dia_util.h',
- 'windows/guid_string.cc',
- 'windows/guid_string.h',
- 'windows/http_upload.cc',
- 'windows/http_upload.h',
- 'windows/omap.cc',
- 'windows/omap.h',
- 'windows/omap_internal.h',
- 'windows/pdb_source_line_writer.cc',
- 'windows/pdb_source_line_writer.h',
- 'windows/string_utils-inl.h',
- 'windows/string_utils.cc',
- ],
- 'include_dirs': [
- '..',
- ],
- },
- {
- 'target_name': 'common_unittests',
- 'type': 'executable',
- 'sources': [
- 'android/breakpad_getcontext_unittest.cc',
- 'byte_cursor_unittest.cc',
- 'dwarf/bytereader_unittest.cc',
- 'dwarf/dwarf2diehandler_unittest.cc',
- 'dwarf/dwarf2reader_cfi_unittest.cc',
- 'dwarf/dwarf2reader_die_unittest.cc',
- 'dwarf_cfi_to_module_unittest.cc',
- 'dwarf_cu_to_module_unittest.cc',
- 'dwarf_line_to_module_unittest.cc',
- 'linux/dump_symbols_unittest.cc',
- 'linux/elf_core_dump_unittest.cc',
- 'linux/elf_symbols_to_module_unittest.cc',
- 'linux/file_id_unittest.cc',
- 'linux/google_crashdump_uploader_test.cc',
- 'linux/linux_libc_support_unittest.cc',
- 'linux/memory_mapped_file_unittest.cc',
- 'linux/safe_readlink_unittest.cc',
- 'linux/synth_elf_unittest.cc',
- 'linux/tests/auto_testfile.h',
- 'linux/tests/crash_generator.cc',
- 'linux/tests/crash_generator.h',
- 'mac/macho_reader_unittest.cc',
- 'memory_range_unittest.cc',
- 'memory_unittest.cc',
- 'module_unittest.cc',
- 'simple_string_dictionary_unittest.cc',
- 'stabs_reader_unittest.cc',
- 'stabs_to_module_unittest.cc',
- 'test_assembler_unittest.cc',
- 'tests/auto_tempdir.h',
- 'tests/file_utils.cc',
- 'tests/file_utils.h',
- 'windows/omap_unittest.cc',
- ],
- 'include_dirs': [
- '..',
- ],
- 'dependencies': [
- 'common',
- '../build/testing.gypi:gmock_main',
- '../build/testing.gypi:gmock',
- '../build/testing.gypi:gtest',
- ],
- 'libraries': [
- '-ldl',
- ],
- },
- ],
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c
deleted file mode 100644
index 12a3c8917..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.c
+++ /dev/null
@@ -1,554 +0,0 @@
-/*
- * Copyright © 1991-2015 Unicode, Inc. All rights reserved.
- * Distributed under the Terms of Use in
- * http://www.unicode.org/copyright.html.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of the Unicode data files and any associated documentation
- * (the "Data Files") or Unicode software and any associated documentation
- * (the "Software") to deal in the Data Files or Software
- * without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, and/or sell copies of
- * the Data Files or Software, and to permit persons to whom the Data Files
- * or Software are furnished to do so, provided that
- * (a) this copyright and permission notice appear with all copies
- * of the Data Files or Software,
- * (b) this copyright and permission notice appear in associated
- * documentation, and
- * (c) there is clear notice in each modified Data File or in the Software
- * as well as in the documentation associated with the Data File(s) or
- * Software that the data or software has been modified.
- *
- * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
- * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
- * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
- * DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THE DATA FILES OR SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder
- * shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in these Data Files or Software without prior
- * written authorization of the copyright holder.
- */
-
-/* ---------------------------------------------------------------------
-
-Conversions between UTF32, UTF-16, and UTF-8. Source code file.
-Author: Mark E. Davis, 1994.
-Rev History: Rick McGowan, fixes & updates May 2001.
-Sept 2001: fixed const & error conditions per
-mods suggested by S. Parent & A. Lillich.
-June 2002: Tim Dodd added detection and handling of incomplete
-source sequences, enhanced error detection, added casts
-to eliminate compiler warnings.
-July 2003: slight mods to back out aggressive FFFE detection.
-Jan 2004: updated switches in from-UTF8 conversions.
-Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
-
-See the header file "ConvertUTF.h" for complete documentation.
-
------------------------------------------------------------------------- */
-
-
-#include "convert_UTF.h"
-#ifdef CVTUTF_DEBUG
-#include <stdio.h>
-#endif
-
-static const int halfShift = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-#define UNI_SUR_HIGH_START (UTF32)0xD800
-#define UNI_SUR_HIGH_END (UTF32)0xDBFF
-#define UNI_SUR_LOW_START (UTF32)0xDC00
-#define UNI_SUR_LOW_END (UTF32)0xDFFF
-
-#ifndef false
-#define false 0
-#endif
-#ifndef true
-#define true 1
-#endif
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
- ch = *source++;
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_LEGAL_UTF32) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- --source; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
-*sourceStart = source;
-*targetStart = target;
-return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF32* target = *targetStart;
- UTF32 ch, ch2;
- while (source < sourceEnd) {
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- if (target >= targetEnd) {
- source = oldSource; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- *target++ = ch;
- }
- *sourceStart = source;
- *targetStart = target;
-#ifdef CVTUTF_DEBUG
- if (result == sourceIllegal) {
- fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2);
- fflush(stderr);
- }
-#endif
- return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
-
-/*
- * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
- * into the first byte, depending on how many bytes follow. There are
- * as many entries in this table as there are UTF-8 sequence types.
- * (I.e., one byte sequence, two byte... etc.). Remember that sequencs
- * for *legal* UTF-8 will be 4 or fewer bytes total.
- */
-static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
-
-/* --------------------------------------------------------------------- */
-
-/* The interface converts a whole buffer to avoid function-call overhead.
-* Constants have been gathered. Loops & conditionals have been removed as
-* much as possible for efficiency, in favor of drop-through switches.
-* (See "Note A" at the bottom of the file for equivalent code.)
-* If your compiler supports it, the "isLegalUTF8" call can be turned
-* into an inline function.
-*/
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF16* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- UTF32 ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /* Figure out how many bytes the result will require */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
-*sourceStart = source;
-*targetStart = target;
-return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- * length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns false. The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-
-static Boolean isLegalUTF8(const UTF8 *source, int length) {
- UTF8 a;
- const UTF8 *srcptr = source+length;
- switch (length) {
- default: return false;
- /* Everything else falls through when "true"... */
- case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
- case 2: if ((a = (*--srcptr)) > 0xBF) return false;
-
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return false; break;
- case 0xED: if (a > 0x9F) return false; break;
- case 0xF0: if (a < 0x90) return false; break;
- case 0xF4: if (a > 0x8F) return false; break;
- default: if (a < 0x80) return false;
- }
-
- case 1: if (*source >= 0x80 && *source < 0xC2) return false;
- }
- if (*source > 0xF4) return false;
- return true;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Exported function to return whether a UTF-8 sequence is legal or not.
- * This is not used here; it's just exported.
- */
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
- int length = trailingBytesForUTF8[*source]+1;
- if (source+length > sourceEnd) {
- return false;
- }
- return isLegalUTF8(source, length);
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF16* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_UTF16) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- source -= (extraBytesToRead+1); /* return to the start */
- break; /* Bail out; shouldn't continue */
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
- }
-*sourceStart = source;
-*targetStart = target;
-return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF32* source = *sourceStart;
- UTF8* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- ch = *source++;
- if (flags == strictConversion ) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /*
- * Figure out how many bytes the result will require. Turn any
- * illegally large UTF32 things (> Plane 17) into replacement chars.
- */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- result = sourceIllegal;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- --source; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
- }
-*sourceStart = source;
-*targetStart = target;
-return result;
-}
-
-/* --------------------------------------------------------------------- */
-
-ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
- ConversionResult result = conversionOK;
- const UTF8* source = *sourceStart;
- UTF32* target = *targetStart;
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6;
- case 4: ch += *source++; ch <<= 6;
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up the source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_LEGAL_UTF32) {
- /*
- * UTF-16 surrogate values are illegal in UTF-32, and anything
- * over Plane 17 (> 0x10FFFF) is illegal.
- */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = ch;
- }
- } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
- result = sourceIllegal;
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- }
- *sourceStart = source;
- *targetStart = target;
- return result;
-}
-
-/* ---------------------------------------------------------------------
-
-Note A.
-The fall-through switches in UTF-8 reading code save a
-temp variable, some decrements & conditionals. The switches
-are equivalent to the following loop:
-{
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
-}
-In UTF-8 writing code, the switches on "bytesToWrite" are
-similarly unrolled loops.
-
---------------------------------------------------------------------- */
diff --git a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h b/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h
deleted file mode 100644
index 644d09950..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/convert_UTF.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright © 1991-2015 Unicode, Inc. All rights reserved.
- * Distributed under the Terms of Use in
- * http://www.unicode.org/copyright.html.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of the Unicode data files and any associated documentation
- * (the "Data Files") or Unicode software and any associated documentation
- * (the "Software") to deal in the Data Files or Software
- * without restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, and/or sell copies of
- * the Data Files or Software, and to permit persons to whom the Data Files
- * or Software are furnished to do so, provided that
- * (a) this copyright and permission notice appear with all copies
- * of the Data Files or Software,
- * (b) this copyright and permission notice appear in associated
- * documentation, and
- * (c) there is clear notice in each modified Data File or in the Software
- * as well as in the documentation associated with the Data File(s) or
- * Software that the data or software has been modified.
- *
- * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
- * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT OF THIRD PARTY RIGHTS.
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
- * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
- * DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THE DATA FILES OR SOFTWARE.
- *
- * Except as contained in this notice, the name of a copyright holder
- * shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in these Data Files or Software without prior
- * written authorization of the copyright holder.
- */
-
-#ifndef COMMON_CONVERT_UTF_H_
-#define COMMON_CONVERT_UTF_H_
-
-/* ---------------------------------------------------------------------
-
-Conversions between UTF32, UTF-16, and UTF-8. Header file.
-
-Several funtions are included here, forming a complete set of
-conversions between the three formats. UTF-7 is not included
-here, but is handled in a separate source file.
-
-Each of these routines takes pointers to input buffers and output
-buffers. The input buffers are const.
-
-Each routine converts the text between *sourceStart and sourceEnd,
-putting the result into the buffer between *targetStart and
-targetEnd. Note: the end pointers are *after* the last item: e.g.
-*(sourceEnd - 1) is the last item.
-
-The return result indicates whether the conversion was successful,
-and if not, whether the problem was in the source or target buffers.
-(Only the first encountered problem is indicated.)
-
-After the conversion, *sourceStart and *targetStart are both
-updated to point to the end of last text successfully converted in
-the respective buffers.
-
-Input parameters:
-sourceStart - pointer to a pointer to the source buffer.
-The contents of this are modified on return so that
-it points at the next thing to be converted.
-targetStart - similarly, pointer to pointer to the target buffer.
-sourceEnd, targetEnd - respectively pointers to the ends of the
-two buffers, for overflow checking only.
-
-These conversion functions take a ConversionFlags argument. When this
-flag is set to strict, both irregular sequences and isolated surrogates
-will cause an error. When the flag is set to lenient, both irregular
-sequences and isolated surrogates are converted.
-
-Whether the flag is strict or lenient, all illegal sequences will cause
-an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
-or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
-must check for illegal sequences.
-
-When the flag is set to lenient, characters over 0x10FFFF are converted
-to the replacement character; otherwise (when the flag is set to strict)
-they constitute an error.
-
-Output parameters:
-The value "sourceIllegal" is returned from some routines if the input
-sequence is malformed. When "sourceIllegal" is returned, the source
-value will point to the illegal value that caused the problem. E.g.,
-in UTF-8 when a sequence is malformed, it points to the start of the
-malformed sequence.
-
-Author: Mark E. Davis, 1994.
-Rev History: Rick McGowan, fixes & updates May 2001.
-Fixes & updates, Sept 2001.
-
------------------------------------------------------------------------- */
-
-/* ---------------------------------------------------------------------
-The following 4 definitions are compiler-specific.
-The C standard does not guarantee that wchar_t has at least
-16 bits, so wchar_t is no less portable than unsigned short!
-All should be unsigned values to avoid sign extension during
-bit mask & shift operations.
------------------------------------------------------------------------- */
-
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-typedef unsigned char Boolean; /* 0 or 1 */
-
-/* Some fundamental constants */
-#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
-#define UNI_MAX_BMP (UTF32)0x0000FFFF
-#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
-#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
-#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
-
-typedef enum {
- conversionOK, /* conversion successful */
- sourceExhausted, /* partial character in source, but hit end */
- targetExhausted, /* insuff. room in target for conversion */
- sourceIllegal /* source sequence is illegal/malformed */
-} ConversionResult;
-
-typedef enum {
- strictConversion = 0,
- lenientConversion
-} ConversionFlags;
-
-/* This is for C++ and does no harm in C */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-ConversionResult ConvertUTF8toUTF16 (const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF16toUTF8 (const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF8toUTF32 (const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF8 (const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF16toUTF32 (const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
-
-ConversionResult ConvertUTF32toUTF16 (const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
-
-Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
-
-#ifdef __cplusplus
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-#endif // COMMON_CONVERT_UTF_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h
deleted file mode 100644
index 42c92f943..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader-inl.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 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.
-
-#ifndef UTIL_DEBUGINFO_BYTEREADER_INL_H__
-#define UTIL_DEBUGINFO_BYTEREADER_INL_H__
-
-#include "common/dwarf/bytereader.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-namespace dwarf2reader {
-
-inline uint8 ByteReader::ReadOneByte(const uint8_t *buffer) const {
- return buffer[0];
-}
-
-inline uint16 ByteReader::ReadTwoBytes(const uint8_t *buffer) const {
- const uint16 buffer0 = buffer[0];
- const uint16 buffer1 = buffer[1];
- if (endian_ == ENDIANNESS_LITTLE) {
- return buffer0 | buffer1 << 8;
- } else {
- return buffer1 | buffer0 << 8;
- }
-}
-
-inline uint64 ByteReader::ReadFourBytes(const uint8_t *buffer) const {
- const uint32 buffer0 = buffer[0];
- const uint32 buffer1 = buffer[1];
- const uint32 buffer2 = buffer[2];
- const uint32 buffer3 = buffer[3];
- if (endian_ == ENDIANNESS_LITTLE) {
- return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24;
- } else {
- return buffer3 | buffer2 << 8 | buffer1 << 16 | buffer0 << 24;
- }
-}
-
-inline uint64 ByteReader::ReadEightBytes(const uint8_t *buffer) const {
- const uint64 buffer0 = buffer[0];
- const uint64 buffer1 = buffer[1];
- const uint64 buffer2 = buffer[2];
- const uint64 buffer3 = buffer[3];
- const uint64 buffer4 = buffer[4];
- const uint64 buffer5 = buffer[5];
- const uint64 buffer6 = buffer[6];
- const uint64 buffer7 = buffer[7];
- if (endian_ == ENDIANNESS_LITTLE) {
- return buffer0 | buffer1 << 8 | buffer2 << 16 | buffer3 << 24 |
- buffer4 << 32 | buffer5 << 40 | buffer6 << 48 | buffer7 << 56;
- } else {
- return buffer7 | buffer6 << 8 | buffer5 << 16 | buffer4 << 24 |
- buffer3 << 32 | buffer2 << 40 | buffer1 << 48 | buffer0 << 56;
- }
-}
-
-// Read an unsigned LEB128 number. Each byte contains 7 bits of
-// information, plus one bit saying whether the number continues or
-// not.
-
-inline uint64 ByteReader::ReadUnsignedLEB128(const uint8_t *buffer,
- size_t* len) const {
- uint64 result = 0;
- size_t num_read = 0;
- unsigned int shift = 0;
- uint8_t byte;
-
- do {
- byte = *buffer++;
- num_read++;
-
- result |= (static_cast<uint64>(byte & 0x7f)) << shift;
-
- shift += 7;
-
- } while (byte & 0x80);
-
- *len = num_read;
-
- return result;
-}
-
-// Read a signed LEB128 number. These are like regular LEB128
-// numbers, except the last byte may have a sign bit set.
-
-inline int64 ByteReader::ReadSignedLEB128(const uint8_t *buffer,
- size_t* len) const {
- int64 result = 0;
- unsigned int shift = 0;
- size_t num_read = 0;
- uint8_t byte;
-
- do {
- byte = *buffer++;
- num_read++;
- result |= (static_cast<uint64>(byte & 0x7f) << shift);
- shift += 7;
- } while (byte & 0x80);
-
- if ((shift < 8 * sizeof (result)) && (byte & 0x40))
- result |= -((static_cast<int64>(1)) << shift);
- *len = num_read;
- return result;
-}
-
-inline uint64 ByteReader::ReadOffset(const uint8_t *buffer) const {
- assert(this->offset_reader_);
- return (this->*offset_reader_)(buffer);
-}
-
-inline uint64 ByteReader::ReadAddress(const uint8_t *buffer) const {
- assert(this->address_reader_);
- return (this->*address_reader_)(buffer);
-}
-
-inline void ByteReader::SetCFIDataBase(uint64 section_base,
- const uint8_t *buffer_base) {
- section_base_ = section_base;
- buffer_base_ = buffer_base;
- have_section_base_ = true;
-}
-
-inline void ByteReader::SetTextBase(uint64 text_base) {
- text_base_ = text_base;
- have_text_base_ = true;
-}
-
-inline void ByteReader::SetDataBase(uint64 data_base) {
- data_base_ = data_base;
- have_data_base_ = true;
-}
-
-inline void ByteReader::SetFunctionBase(uint64 function_base) {
- function_base_ = function_base;
- have_function_base_ = true;
-}
-
-inline void ByteReader::ClearFunctionBase() {
- have_function_base_ = false;
-}
-
-} // namespace dwarf2reader
-
-#endif // UTIL_DEBUGINFO_BYTEREADER_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc
deleted file mode 100644
index 14b43adb8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-// 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 <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/bytereader.h"
-
-namespace dwarf2reader {
-
-ByteReader::ByteReader(enum Endianness endian)
- :offset_reader_(NULL), address_reader_(NULL), endian_(endian),
- address_size_(0), offset_size_(0),
- have_section_base_(), have_text_base_(), have_data_base_(),
- have_function_base_() { }
-
-ByteReader::~ByteReader() { }
-
-void ByteReader::SetOffsetSize(uint8 size) {
- offset_size_ = size;
- assert(size == 4 || size == 8);
- if (size == 4) {
- this->offset_reader_ = &ByteReader::ReadFourBytes;
- } else {
- this->offset_reader_ = &ByteReader::ReadEightBytes;
- }
-}
-
-void ByteReader::SetAddressSize(uint8 size) {
- address_size_ = size;
- assert(size == 4 || size == 8);
- if (size == 4) {
- this->address_reader_ = &ByteReader::ReadFourBytes;
- } else {
- this->address_reader_ = &ByteReader::ReadEightBytes;
- }
-}
-
-uint64 ByteReader::ReadInitialLength(const uint8_t *start, size_t* len) {
- const uint64 initial_length = ReadFourBytes(start);
- start += 4;
-
- // In DWARF2/3, if the initial length is all 1 bits, then the offset
- // size is 8 and we need to read the next 8 bytes for the real length.
- if (initial_length == 0xffffffff) {
- SetOffsetSize(8);
- *len = 12;
- return ReadOffset(start);
- } else {
- SetOffsetSize(4);
- *len = 4;
- }
- return initial_length;
-}
-
-bool ByteReader::ValidEncoding(DwarfPointerEncoding encoding) const {
- if (encoding == DW_EH_PE_omit) return true;
- if (encoding == DW_EH_PE_aligned) return true;
- if ((encoding & 0x7) > DW_EH_PE_udata8)
- return false;
- if ((encoding & 0x70) > DW_EH_PE_funcrel)
- return false;
- return true;
-}
-
-bool ByteReader::UsableEncoding(DwarfPointerEncoding encoding) const {
- switch (encoding & 0x70) {
- case DW_EH_PE_absptr: return true;
- case DW_EH_PE_pcrel: return have_section_base_;
- case DW_EH_PE_textrel: return have_text_base_;
- case DW_EH_PE_datarel: return have_data_base_;
- case DW_EH_PE_funcrel: return have_function_base_;
- default: return false;
- }
-}
-
-uint64 ByteReader::ReadEncodedPointer(const uint8_t *buffer,
- DwarfPointerEncoding encoding,
- size_t *len) const {
- // UsableEncoding doesn't approve of DW_EH_PE_omit, so we shouldn't
- // see it here.
- assert(encoding != DW_EH_PE_omit);
-
- // The Linux Standards Base 4.0 does not make this clear, but the
- // GNU tools (gcc/unwind-pe.h; readelf/dwarf.c; gdb/dwarf2-frame.c)
- // agree that aligned pointers are always absolute, machine-sized,
- // machine-signed pointers.
- if (encoding == DW_EH_PE_aligned) {
- assert(have_section_base_);
-
- // We don't need to align BUFFER in *our* address space. Rather, we
- // need to find the next position in our buffer that would be aligned
- // when the .eh_frame section the buffer contains is loaded into the
- // program's memory. So align assuming that buffer_base_ gets loaded at
- // address section_base_, where section_base_ itself may or may not be
- // aligned.
-
- // First, find the offset to START from the closest prior aligned
- // address.
- uint64 skew = section_base_ & (AddressSize() - 1);
- // Now find the offset from that aligned address to buffer.
- uint64 offset = skew + (buffer - buffer_base_);
- // Round up to the next boundary.
- uint64 aligned = (offset + AddressSize() - 1) & -AddressSize();
- // Convert back to a pointer.
- const uint8_t *aligned_buffer = buffer_base_ + (aligned - skew);
- // Finally, store the length and actually fetch the pointer.
- *len = aligned_buffer - buffer + AddressSize();
- return ReadAddress(aligned_buffer);
- }
-
- // Extract the value first, ignoring whether it's a pointer or an
- // offset relative to some base.
- uint64 offset;
- switch (encoding & 0x0f) {
- case DW_EH_PE_absptr:
- // DW_EH_PE_absptr is weird, as it is used as a meaningful value for
- // both the high and low nybble of encoding bytes. When it appears in
- // the high nybble, it means that the pointer is absolute, not an
- // offset from some base address. When it appears in the low nybble,
- // as here, it means that the pointer is stored as a normal
- // machine-sized and machine-signed address. A low nybble of
- // DW_EH_PE_absptr does not imply that the pointer is absolute; it is
- // correct for us to treat the value as an offset from a base address
- // if the upper nybble is not DW_EH_PE_absptr.
- offset = ReadAddress(buffer);
- *len = AddressSize();
- break;
-
- case DW_EH_PE_uleb128:
- offset = ReadUnsignedLEB128(buffer, len);
- break;
-
- case DW_EH_PE_udata2:
- offset = ReadTwoBytes(buffer);
- *len = 2;
- break;
-
- case DW_EH_PE_udata4:
- offset = ReadFourBytes(buffer);
- *len = 4;
- break;
-
- case DW_EH_PE_udata8:
- offset = ReadEightBytes(buffer);
- *len = 8;
- break;
-
- case DW_EH_PE_sleb128:
- offset = ReadSignedLEB128(buffer, len);
- break;
-
- case DW_EH_PE_sdata2:
- offset = ReadTwoBytes(buffer);
- // Sign-extend from 16 bits.
- offset = (offset ^ 0x8000) - 0x8000;
- *len = 2;
- break;
-
- case DW_EH_PE_sdata4:
- offset = ReadFourBytes(buffer);
- // Sign-extend from 32 bits.
- offset = (offset ^ 0x80000000ULL) - 0x80000000ULL;
- *len = 4;
- break;
-
- case DW_EH_PE_sdata8:
- // No need to sign-extend; this is the full width of our type.
- offset = ReadEightBytes(buffer);
- *len = 8;
- break;
-
- default:
- abort();
- }
-
- // Find the appropriate base address.
- uint64 base;
- switch (encoding & 0x70) {
- case DW_EH_PE_absptr:
- base = 0;
- break;
-
- case DW_EH_PE_pcrel:
- assert(have_section_base_);
- base = section_base_ + (buffer - buffer_base_);
- break;
-
- case DW_EH_PE_textrel:
- assert(have_text_base_);
- base = text_base_;
- break;
-
- case DW_EH_PE_datarel:
- assert(have_data_base_);
- base = data_base_;
- break;
-
- case DW_EH_PE_funcrel:
- assert(have_function_base_);
- base = function_base_;
- break;
-
- default:
- abort();
- }
-
- uint64 pointer = base + offset;
-
- // Remove inappropriate upper bits.
- if (AddressSize() == 4)
- pointer = pointer & 0xffffffff;
- else
- assert(AddressSize() == sizeof(uint64));
-
- return pointer;
-}
-
-Endianness ByteReader::GetEndianness() const {
- return endian_;
-}
-
-} // namespace dwarf2reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h
deleted file mode 100644
index 59d430348..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader.h
+++ /dev/null
@@ -1,315 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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 COMMON_DWARF_BYTEREADER_H__
-#define COMMON_DWARF_BYTEREADER_H__
-
-#include <stdint.h>
-
-#include <string>
-
-#include "common/dwarf/types.h"
-#include "common/dwarf/dwarf2enums.h"
-
-namespace dwarf2reader {
-
-// We can't use the obvious name of LITTLE_ENDIAN and BIG_ENDIAN
-// because it conflicts with a macro
-enum Endianness {
- ENDIANNESS_BIG,
- ENDIANNESS_LITTLE
-};
-
-// A ByteReader knows how to read single- and multi-byte values of
-// various endiannesses, sizes, and encodings, as used in DWARF
-// debugging information and Linux C++ exception handling data.
-class ByteReader {
- public:
- // Construct a ByteReader capable of reading one-, two-, four-, and
- // eight-byte values according to ENDIANNESS, absolute machine-sized
- // addresses, DWARF-style "initial length" values, signed and
- // unsigned LEB128 numbers, and Linux C++ exception handling data's
- // encoded pointers.
- explicit ByteReader(enum Endianness endianness);
- virtual ~ByteReader();
-
- // Read a single byte from BUFFER and return it as an unsigned 8 bit
- // number.
- uint8 ReadOneByte(const uint8_t *buffer) const;
-
- // Read two bytes from BUFFER and return them as an unsigned 16 bit
- // number, using this ByteReader's endianness.
- uint16 ReadTwoBytes(const uint8_t *buffer) const;
-
- // Read four bytes from BUFFER and return them as an unsigned 32 bit
- // number, using this ByteReader's endianness. This function returns
- // a uint64 so that it is compatible with ReadAddress and
- // ReadOffset. The number it returns will never be outside the range
- // of an unsigned 32 bit integer.
- uint64 ReadFourBytes(const uint8_t *buffer) const;
-
- // Read eight bytes from BUFFER and return them as an unsigned 64
- // bit number, using this ByteReader's endianness.
- uint64 ReadEightBytes(const uint8_t *buffer) const;
-
- // Read an unsigned LEB128 (Little Endian Base 128) number from
- // BUFFER and return it as an unsigned 64 bit integer. Set LEN to
- // the number of bytes read.
- //
- // The unsigned LEB128 representation of an integer N is a variable
- // number of bytes:
- //
- // - If N is between 0 and 0x7f, then its unsigned LEB128
- // representation is a single byte whose value is N.
- //
- // - Otherwise, its unsigned LEB128 representation is (N & 0x7f) |
- // 0x80, followed by the unsigned LEB128 representation of N /
- // 128, rounded towards negative infinity.
- //
- // In other words, we break VALUE into groups of seven bits, put
- // them in little-endian order, and then write them as eight-bit
- // bytes with the high bit on all but the last.
- uint64 ReadUnsignedLEB128(const uint8_t *buffer, size_t *len) const;
-
- // Read a signed LEB128 number from BUFFER and return it as an
- // signed 64 bit integer. Set LEN to the number of bytes read.
- //
- // The signed LEB128 representation of an integer N is a variable
- // number of bytes:
- //
- // - If N is between -0x40 and 0x3f, then its signed LEB128
- // representation is a single byte whose value is N in two's
- // complement.
- //
- // - Otherwise, its signed LEB128 representation is (N & 0x7f) |
- // 0x80, followed by the signed LEB128 representation of N / 128,
- // rounded towards negative infinity.
- //
- // In other words, we break VALUE into groups of seven bits, put
- // them in little-endian order, and then write them as eight-bit
- // bytes with the high bit on all but the last.
- int64 ReadSignedLEB128(const uint8_t *buffer, size_t *len) const;
-
- // Indicate that addresses on this architecture are SIZE bytes long. SIZE
- // must be either 4 or 8. (DWARF allows addresses to be any number of
- // bytes in length from 1 to 255, but we only support 32- and 64-bit
- // addresses at the moment.) You must call this before using the
- // ReadAddress member function.
- //
- // For data in a .debug_info section, or something that .debug_info
- // refers to like line number or macro data, the compilation unit
- // header's address_size field indicates the address size to use. Call
- // frame information doesn't indicate its address size (a shortcoming of
- // the spec); you must supply the appropriate size based on the
- // architecture of the target machine.
- void SetAddressSize(uint8 size);
-
- // Return the current address size, in bytes. This is either 4,
- // indicating 32-bit addresses, or 8, indicating 64-bit addresses.
- uint8 AddressSize() const { return address_size_; }
-
- // Read an address from BUFFER and return it as an unsigned 64 bit
- // integer, respecting this ByteReader's endianness and address size. You
- // must call SetAddressSize before calling this function.
- uint64 ReadAddress(const uint8_t *buffer) const;
-
- // DWARF actually defines two slightly different formats: 32-bit DWARF
- // and 64-bit DWARF. This is *not* related to the size of registers or
- // addresses on the target machine; it refers only to the size of section
- // offsets and data lengths appearing in the DWARF data. One only needs
- // 64-bit DWARF when the debugging data itself is larger than 4GiB.
- // 32-bit DWARF can handle x86_64 or PPC64 code just fine, unless the
- // debugging data itself is very large.
- //
- // DWARF information identifies itself as 32-bit or 64-bit DWARF: each
- // compilation unit and call frame information entry begins with an
- // "initial length" field, which, in addition to giving the length of the
- // data, also indicates the size of section offsets and lengths appearing
- // in that data. The ReadInitialLength member function, below, reads an
- // initial length and sets the ByteReader's offset size as a side effect.
- // Thus, in the normal process of reading DWARF data, the appropriate
- // offset size is set automatically. So, you should only need to call
- // SetOffsetSize if you are using the same ByteReader to jump from the
- // midst of one block of DWARF data into another.
-
- // Read a DWARF "initial length" field from START, and return it as
- // an unsigned 64 bit integer, respecting this ByteReader's
- // endianness. Set *LEN to the length of the initial length in
- // bytes, either four or twelve. As a side effect, set this
- // ByteReader's offset size to either 4 (if we see a 32-bit DWARF
- // initial length) or 8 (if we see a 64-bit DWARF initial length).
- //
- // A DWARF initial length is either:
- //
- // - a byte count stored as an unsigned 32-bit value less than
- // 0xffffff00, indicating that the data whose length is being
- // measured uses the 32-bit DWARF format, or
- //
- // - The 32-bit value 0xffffffff, followed by a 64-bit byte count,
- // indicating that the data whose length is being measured uses
- // the 64-bit DWARF format.
- uint64 ReadInitialLength(const uint8_t *start, size_t *len);
-
- // Read an offset from BUFFER and return it as an unsigned 64 bit
- // integer, respecting the ByteReader's endianness. In 32-bit DWARF, the
- // offset is 4 bytes long; in 64-bit DWARF, the offset is eight bytes
- // long. You must call ReadInitialLength or SetOffsetSize before calling
- // this function; see the comments above for details.
- uint64 ReadOffset(const uint8_t *buffer) const;
-
- // Return the current offset size, in bytes.
- // A return value of 4 indicates that we are reading 32-bit DWARF.
- // A return value of 8 indicates that we are reading 64-bit DWARF.
- uint8 OffsetSize() const { return offset_size_; }
-
- // Indicate that section offsets and lengths are SIZE bytes long. SIZE
- // must be either 4 (meaning 32-bit DWARF) or 8 (meaning 64-bit DWARF).
- // Usually, you should not call this function yourself; instead, let a
- // call to ReadInitialLength establish the data's offset size
- // automatically.
- void SetOffsetSize(uint8 size);
-
- // The Linux C++ ABI uses a variant of DWARF call frame information
- // for exception handling. This data is included in the program's
- // address space as the ".eh_frame" section, and intepreted at
- // runtime to walk the stack, find exception handlers, and run
- // cleanup code. The format is mostly the same as DWARF CFI, with
- // some adjustments made to provide the additional
- // exception-handling data, and to make the data easier to work with
- // in memory --- for example, to allow it to be placed in read-only
- // memory even when describing position-independent code.
- //
- // In particular, exception handling data can select a number of
- // different encodings for pointers that appear in the data, as
- // described by the DwarfPointerEncoding enum. There are actually
- // four axes(!) to the encoding:
- //
- // - The pointer size: pointers can be 2, 4, or 8 bytes long, or use
- // the DWARF LEB128 encoding.
- //
- // - The pointer's signedness: pointers can be signed or unsigned.
- //
- // - The pointer's base address: the data stored in the exception
- // handling data can be the actual address (that is, an absolute
- // pointer), or relative to one of a number of different base
- // addreses --- including that of the encoded pointer itself, for
- // a form of "pc-relative" addressing.
- //
- // - The pointer may be indirect: it may be the address where the
- // true pointer is stored. (This is used to refer to things via
- // global offset table entries, program linkage table entries, or
- // other tricks used in position-independent code.)
- //
- // There are also two options that fall outside that matrix
- // altogether: the pointer may be omitted, or it may have padding to
- // align it on an appropriate address boundary. (That last option
- // may seem like it should be just another axis, but it is not.)
-
- // Indicate that the exception handling data is loaded starting at
- // SECTION_BASE, and that the start of its buffer in our own memory
- // is BUFFER_BASE. This allows us to find the address that a given
- // byte in our buffer would have when loaded into the program the
- // data describes. We need this to resolve DW_EH_PE_pcrel pointers.
- void SetCFIDataBase(uint64 section_base, const uint8_t *buffer_base);
-
- // Indicate that the base address of the program's ".text" section
- // is TEXT_BASE. We need this to resolve DW_EH_PE_textrel pointers.
- void SetTextBase(uint64 text_base);
-
- // Indicate that the base address for DW_EH_PE_datarel pointers is
- // DATA_BASE. The proper value depends on the ABI; it is usually the
- // address of the global offset table, held in a designated register in
- // position-independent code. You will need to look at the startup code
- // for the target system to be sure. I tried; my eyes bled.
- void SetDataBase(uint64 data_base);
-
- // Indicate that the base address for the FDE we are processing is
- // FUNCTION_BASE. This is the start address of DW_EH_PE_funcrel
- // pointers. (This encoding does not seem to be used by the GNU
- // toolchain.)
- void SetFunctionBase(uint64 function_base);
-
- // Indicate that we are no longer processing any FDE, so any use of
- // a DW_EH_PE_funcrel encoding is an error.
- void ClearFunctionBase();
-
- // Return true if ENCODING is a valid pointer encoding.
- bool ValidEncoding(DwarfPointerEncoding encoding) const;
-
- // Return true if we have all the information we need to read a
- // pointer that uses ENCODING. This checks that the appropriate
- // SetFooBase function for ENCODING has been called.
- bool UsableEncoding(DwarfPointerEncoding encoding) const;
-
- // Read an encoded pointer from BUFFER using ENCODING; return the
- // absolute address it represents, and set *LEN to the pointer's
- // length in bytes, including any padding for aligned pointers.
- //
- // This function calls 'abort' if ENCODING is invalid or refers to a
- // base address this reader hasn't been given, so you should check
- // with ValidEncoding and UsableEncoding first if you would rather
- // die in a more helpful way.
- uint64 ReadEncodedPointer(const uint8_t *buffer,
- DwarfPointerEncoding encoding,
- size_t *len) const;
-
- Endianness GetEndianness() const;
- private:
-
- // Function pointer type for our address and offset readers.
- typedef uint64 (ByteReader::*AddressReader)(const uint8_t *) const;
-
- // Read an offset from BUFFER and return it as an unsigned 64 bit
- // integer. DWARF2/3 define offsets as either 4 or 8 bytes,
- // generally depending on the amount of DWARF2/3 info present.
- // This function pointer gets set by SetOffsetSize.
- AddressReader offset_reader_;
-
- // Read an address from BUFFER and return it as an unsigned 64 bit
- // integer. DWARF2/3 allow addresses to be any size from 0-255
- // bytes currently. Internally we support 4 and 8 byte addresses,
- // and will CHECK on anything else.
- // This function pointer gets set by SetAddressSize.
- AddressReader address_reader_;
-
- Endianness endian_;
- uint8 address_size_;
- uint8 offset_size_;
-
- // Base addresses for Linux C++ exception handling data's encoded pointers.
- bool have_section_base_, have_text_base_, have_data_base_;
- bool have_function_base_;
- uint64 section_base_, text_base_, data_base_, function_base_;
- const uint8_t *buffer_base_;
-};
-
-} // namespace dwarf2reader
-
-#endif // COMMON_DWARF_BYTEREADER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader_unittest.cc
deleted file mode 100644
index e66062d1f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/bytereader_unittest.cc
+++ /dev/null
@@ -1,707 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// bytereader_unittest.cc: Unit tests for dwarf2reader::ByteReader
-
-#include <stdint.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf/bytereader.h"
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/cfi_assembler.h"
-#include "common/using_std_string.h"
-
-using dwarf2reader::ByteReader;
-using dwarf2reader::DwarfPointerEncoding;
-using dwarf2reader::ENDIANNESS_BIG;
-using dwarf2reader::ENDIANNESS_LITTLE;
-using google_breakpad::CFISection;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Section;
-using testing::Test;
-
-struct ReaderFixture {
- string contents;
- size_t pointer_size;
-};
-
-class Reader: public ReaderFixture, public Test { };
-class ReaderDeathTest: public ReaderFixture, public Test { };
-
-TEST_F(Reader, SimpleConstructor) {
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- CFISection section(kBigEndian, 4);
- section
- .D8(0xc0)
- .D16(0xcf0d)
- .D32(0x96fdd219)
- .D64(0xbbf55fef0825f117ULL)
- .ULEB128(0xa0927048ba8121afULL)
- .LEB128(-0x4f337badf4483f83LL)
- .D32(0xfec319c9);
- ASSERT_TRUE(section.GetContents(&contents));
- const uint8_t *data = reinterpret_cast<const uint8_t *>(contents.data());
- EXPECT_EQ(0xc0U, reader.ReadOneByte(data));
- EXPECT_EQ(0xcf0dU, reader.ReadTwoBytes(data + 1));
- EXPECT_EQ(0x96fdd219U, reader.ReadFourBytes(data + 3));
- EXPECT_EQ(0xbbf55fef0825f117ULL, reader.ReadEightBytes(data + 7));
- size_t leb128_size;
- EXPECT_EQ(0xa0927048ba8121afULL,
- reader.ReadUnsignedLEB128(data + 15, &leb128_size));
- EXPECT_EQ(10U, leb128_size);
- EXPECT_EQ(-0x4f337badf4483f83LL,
- reader.ReadSignedLEB128(data + 25, &leb128_size));
- EXPECT_EQ(10U, leb128_size);
- EXPECT_EQ(0xfec319c9, reader.ReadAddress(data + 35));
-}
-
-TEST_F(Reader, ValidEncodings) {
- ByteReader reader(ENDIANNESS_LITTLE);
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_omit)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_aligned)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_pcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_textrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_datarel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_absptr |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_uleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_udata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sleb128 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata2 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata4 |
- dwarf2reader::DW_EH_PE_funcrel)));
- EXPECT_TRUE(reader.ValidEncoding(
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect |
- dwarf2reader::DW_EH_PE_sdata8 |
- dwarf2reader::DW_EH_PE_funcrel)));
-
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x05)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x07)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x0d)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x0f)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x51)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x60)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0x70)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0xf0)));
- EXPECT_FALSE(reader.ValidEncoding(DwarfPointerEncoding(0xd0)));
-}
-
-TEST_F(ReaderDeathTest, DW_EH_PE_omit) {
- static const uint8_t data[] = { 42 };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- EXPECT_DEATH(reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_omit,
- &pointer_size),
- "encoding != DW_EH_PE_omit");
-}
-
-TEST_F(Reader, DW_EH_PE_absptr4) {
- static const uint8_t data[] = { 0x27, 0x57, 0xea, 0x40 };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(4);
- EXPECT_EQ(0x40ea5727U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_absptr,
- &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_absptr8) {
- static const uint8_t data[] = {
- 0x60, 0x27, 0x57, 0xea, 0x40, 0xc2, 0x98, 0x05, 0x01, 0x50
- };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(8);
- EXPECT_EQ(0x010598c240ea5727ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_absptr,
- &pointer_size));
- EXPECT_EQ(8U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_uleb128) {
- static const uint8_t data[] = { 0x81, 0x84, 0x4c };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(4);
- EXPECT_EQ(0x130201U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_uleb128,
- &pointer_size));
- EXPECT_EQ(3U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_udata2) {
- static const uint8_t data[] = { 0xf4, 0x8d };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- EXPECT_EQ(0xf48dU,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_udata2,
- &pointer_size));
- EXPECT_EQ(2U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_udata4) {
- static const uint8_t data[] = { 0xb2, 0x68, 0xa5, 0x62, 0x8f, 0x8b };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(8);
- EXPECT_EQ(0xa5628f8b,
- reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_udata4,
- &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_udata8Addr8) {
- static const uint8_t data[] = {
- 0x27, 0x04, 0x73, 0x04, 0x69, 0x9f, 0x19, 0xed, 0x8f, 0xfe
- };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(8);
- EXPECT_EQ(0x8fed199f69047304ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
- &pointer_size));
- EXPECT_EQ(8U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_udata8Addr4) {
- static const uint8_t data[] = {
- 0x27, 0x04, 0x73, 0x04, 0x69, 0x9f, 0x19, 0xed, 0x8f, 0xfe
- };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(4);
- EXPECT_EQ(0x69047304ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_udata8,
- &pointer_size));
- EXPECT_EQ(8U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_sleb128) {
- static const uint8_t data[] = { 0x42, 0xff, 0xfb, 0x73 };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- EXPECT_EQ(-0x030201U & 0xffffffff,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sleb128,
- &pointer_size));
- EXPECT_EQ(3U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_sdata2) {
- static const uint8_t data[] = { 0xb9, 0xbf };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(8);
- EXPECT_EQ(0xffffffffffffbfb9ULL,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_sdata2,
- &pointer_size));
- EXPECT_EQ(2U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_sdata4) {
- static const uint8_t data[] = { 0xa0, 0xca, 0xf2, 0xb8, 0xc2, 0xad };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(8);
- EXPECT_EQ(0xffffffffadc2b8f2ULL,
- reader.ReadEncodedPointer(data + 2, dwarf2reader::DW_EH_PE_sdata4,
- &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_sdata8) {
- static const uint8_t data[] = {
- 0xf6, 0x66, 0x57, 0x79, 0xe0, 0x0c, 0x9b, 0x26, 0x87
- };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(8);
- EXPECT_EQ(0x87269b0ce0795766ULL,
- reader.ReadEncodedPointer(data + 1, dwarf2reader::DW_EH_PE_sdata8,
- &pointer_size));
- EXPECT_EQ(8U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_pcrel) {
- static const uint8_t data[] = {
- 0x4a, 0x8b, 0x1b, 0x14, 0xc8, 0xc4, 0x02, 0xce
- };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_pcrel
- | dwarf2reader::DW_EH_PE_absptr);
- reader.SetCFIDataBase(0x89951377, data);
- EXPECT_EQ(0x89951377 + 3 + 0x14c8c402,
- reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_textrel) {
- static const uint8_t data[] = {
- 0xd9, 0x0d, 0x05, 0x17, 0xc9, 0x7a, 0x42, 0x1e
- };
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(4);
- reader.SetTextBase(0xb91beaf0);
- DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_sdata2);
- EXPECT_EQ((0xb91beaf0 + 0xffffc917) & 0xffffffff,
- reader.ReadEncodedPointer(data + 3, encoding, &pointer_size));
- EXPECT_EQ(2U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_datarel) {
- static const uint8_t data[] = {
- 0x16, 0xf2, 0xbb, 0x82, 0x68, 0xa7, 0xbc, 0x39
- };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(8);
- reader.SetDataBase(0xbef308bd25ce74f0ULL);
- DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_sleb128);
- EXPECT_EQ(0xbef308bd25ce74f0ULL + 0xfffffffffffa013bULL,
- reader.ReadEncodedPointer(data + 2, encoding, &pointer_size));
- EXPECT_EQ(3U, pointer_size);
-}
-
-TEST_F(Reader, DW_EH_PE_funcrel) {
- static const uint8_t data[] = {
- 0x84, 0xf8, 0x14, 0x01, 0x61, 0xd1, 0x48, 0xc9
- };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetAddressSize(4);
- reader.SetFunctionBase(0x823c3520);
- DwarfPointerEncoding encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
- | dwarf2reader::DW_EH_PE_udata2);
- EXPECT_EQ(0x823c3520 + 0xd148,
- reader.ReadEncodedPointer(data + 5, encoding, &pointer_size));
- EXPECT_EQ(2U, pointer_size);
-}
-
-TEST(UsableBase, CFI) {
- static const uint8_t data[] = { 0x42 };
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetCFIDataBase(0xb31cbd20, data);
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_omit));
- EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
-}
-
-TEST(UsableBase, Text) {
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetTextBase(0xa899ccb9);
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_omit));
- EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
-}
-
-TEST(UsableBase, Data) {
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetDataBase(0xf7b10bcd);
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_omit));
- EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
-}
-
-TEST(UsableBase, Function) {
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetFunctionBase(0xc2c0ed81);
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_omit));
- EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
-}
-
-TEST(UsableBase, ClearFunction) {
- ByteReader reader(ENDIANNESS_BIG);
- reader.SetFunctionBase(0xc2c0ed81);
- reader.ClearFunctionBase();
- EXPECT_TRUE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_absptr));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_pcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_textrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_datarel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_funcrel));
- EXPECT_FALSE(reader.UsableEncoding(dwarf2reader::DW_EH_PE_omit));
- EXPECT_FALSE(reader.UsableEncoding(DwarfPointerEncoding(0x60)));
-}
-
-struct AlignedFixture {
- AlignedFixture() : reader(ENDIANNESS_BIG) { reader.SetAddressSize(4); }
- static const uint8_t data[10];
- ByteReader reader;
- size_t pointer_size;
-};
-
-const uint8_t AlignedFixture::data[10] = {
- 0xfe, 0x6e, 0x93, 0xd8, 0x34, 0xd5, 0x1c, 0xd3, 0xac, 0x2b
-};
-
-class Aligned: public AlignedFixture, public Test { };
-
-TEST_F(Aligned, DW_EH_PE_aligned0) {
- reader.SetCFIDataBase(0xb440305c, data);
- EXPECT_EQ(0xfe6e93d8U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned1) {
- reader.SetCFIDataBase(0xb440305d, data);
- EXPECT_EQ(0xd834d51cU,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(7U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned2) {
- reader.SetCFIDataBase(0xb440305e, data);
- EXPECT_EQ(0x93d834d5U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(6U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned3) {
- reader.SetCFIDataBase(0xb440305f, data);
- EXPECT_EQ(0x6e93d834U,
- reader.ReadEncodedPointer(data, dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(5U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned11) {
- reader.SetCFIDataBase(0xb4403061, data);
- EXPECT_EQ(0xd834d51cU,
- reader.ReadEncodedPointer(data + 1,
- dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(6U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned30) {
- reader.SetCFIDataBase(0xb4403063, data);
- EXPECT_EQ(0x6e93d834U,
- reader.ReadEncodedPointer(data + 1,
- dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(4U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned23) {
- reader.SetCFIDataBase(0xb4403062, data);
- EXPECT_EQ(0x1cd3ac2bU,
- reader.ReadEncodedPointer(data + 3,
- dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(7U, pointer_size);
-}
-
-TEST_F(Aligned, DW_EH_PE_aligned03) {
- reader.SetCFIDataBase(0xb4403064, data);
- EXPECT_EQ(0x34d51cd3U,
- reader.ReadEncodedPointer(data + 3,
- dwarf2reader::DW_EH_PE_aligned,
- &pointer_size));
- EXPECT_EQ(5U, pointer_size);
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc
deleted file mode 100644
index dbc2efae6..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// cfi_assembler.cc: Implementation of google_breakpad::CFISection class.
-// See cfi_assembler.h for details.
-
-#include "common/dwarf/cfi_assembler.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-namespace google_breakpad {
-
-using dwarf2reader::DwarfPointerEncoding;
-
-CFISection &CFISection::CIEHeader(uint64_t code_alignment_factor,
- int data_alignment_factor,
- unsigned return_address_register,
- uint8_t version,
- const string &augmentation,
- bool dwarf64) {
- assert(!entry_length_);
- entry_length_ = new PendingLength();
- in_fde_ = false;
-
- if (dwarf64) {
- D32(kDwarf64InitialLengthMarker);
- D64(entry_length_->length);
- entry_length_->start = Here();
- D64(eh_frame_ ? kEHFrame64CIEIdentifier : kDwarf64CIEIdentifier);
- } else {
- D32(entry_length_->length);
- entry_length_->start = Here();
- D32(eh_frame_ ? kEHFrame32CIEIdentifier : kDwarf32CIEIdentifier);
- }
- D8(version);
- AppendCString(augmentation);
- ULEB128(code_alignment_factor);
- LEB128(data_alignment_factor);
- if (version == 1)
- D8(return_address_register);
- else
- ULEB128(return_address_register);
- return *this;
-}
-
-CFISection &CFISection::FDEHeader(Label cie_pointer,
- uint64_t initial_location,
- uint64_t address_range,
- bool dwarf64) {
- assert(!entry_length_);
- entry_length_ = new PendingLength();
- in_fde_ = true;
- fde_start_address_ = initial_location;
-
- if (dwarf64) {
- D32(0xffffffff);
- D64(entry_length_->length);
- entry_length_->start = Here();
- if (eh_frame_)
- D64(Here() - cie_pointer);
- else
- D64(cie_pointer);
- } else {
- D32(entry_length_->length);
- entry_length_->start = Here();
- if (eh_frame_)
- D32(Here() - cie_pointer);
- else
- D32(cie_pointer);
- }
- EncodedPointer(initial_location);
- // The FDE length in an .eh_frame section uses the same encoding as the
- // initial location, but ignores the base address (selected by the upper
- // nybble of the encoding), as it's a length, not an address that can be
- // made relative.
- EncodedPointer(address_range,
- DwarfPointerEncoding(pointer_encoding_ & 0x0f));
- return *this;
-}
-
-CFISection &CFISection::FinishEntry() {
- assert(entry_length_);
- Align(address_size_, dwarf2reader::DW_CFA_nop);
- entry_length_->length = Here() - entry_length_->start;
- delete entry_length_;
- entry_length_ = NULL;
- in_fde_ = false;
- return *this;
-}
-
-CFISection &CFISection::EncodedPointer(uint64_t address,
- DwarfPointerEncoding encoding,
- const EncodedPointerBases &bases) {
- // Omitted data is extremely easy to emit.
- if (encoding == dwarf2reader::DW_EH_PE_omit)
- return *this;
-
- // If (encoding & dwarf2reader::DW_EH_PE_indirect) != 0, then we assume
- // that ADDRESS is the address at which the pointer is stored --- in
- // other words, that bit has no effect on how we write the pointer.
- encoding = DwarfPointerEncoding(encoding & ~dwarf2reader::DW_EH_PE_indirect);
-
- // Find the base address to which this pointer is relative. The upper
- // nybble of the encoding specifies this.
- uint64_t base;
- switch (encoding & 0xf0) {
- case dwarf2reader::DW_EH_PE_absptr: base = 0; break;
- case dwarf2reader::DW_EH_PE_pcrel: base = bases.cfi + Size(); break;
- case dwarf2reader::DW_EH_PE_textrel: base = bases.text; break;
- case dwarf2reader::DW_EH_PE_datarel: base = bases.data; break;
- case dwarf2reader::DW_EH_PE_funcrel: base = fde_start_address_; break;
- case dwarf2reader::DW_EH_PE_aligned: base = 0; break;
- default: abort();
- };
-
- // Make ADDRESS relative. Yes, this is appropriate even for "absptr"
- // values; see gcc/unwind-pe.h.
- address -= base;
-
- // Align the pointer, if required.
- if ((encoding & 0xf0) == dwarf2reader::DW_EH_PE_aligned)
- Align(AddressSize());
-
- // Append ADDRESS to this section in the appropriate form. For the
- // fixed-width forms, we don't need to differentiate between signed and
- // unsigned encodings, because ADDRESS has already been extended to 64
- // bits before it was passed to us.
- switch (encoding & 0x0f) {
- case dwarf2reader::DW_EH_PE_absptr:
- Address(address);
- break;
-
- case dwarf2reader::DW_EH_PE_uleb128:
- ULEB128(address);
- break;
-
- case dwarf2reader::DW_EH_PE_sleb128:
- LEB128(address);
- break;
-
- case dwarf2reader::DW_EH_PE_udata2:
- case dwarf2reader::DW_EH_PE_sdata2:
- D16(address);
- break;
-
- case dwarf2reader::DW_EH_PE_udata4:
- case dwarf2reader::DW_EH_PE_sdata4:
- D32(address);
- break;
-
- case dwarf2reader::DW_EH_PE_udata8:
- case dwarf2reader::DW_EH_PE_sdata8:
- D64(address);
- break;
-
- default:
- abort();
- }
-
- return *this;
-};
-
-const uint32_t CFISection::kDwarf64InitialLengthMarker;
-const uint32_t CFISection::kDwarf32CIEIdentifier;
-const uint64_t CFISection::kDwarf64CIEIdentifier;
-const uint32_t CFISection::kEHFrame32CIEIdentifier;
-const uint64_t CFISection::kEHFrame64CIEIdentifier;
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h
deleted file mode 100644
index 227812b58..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/cfi_assembler.h
+++ /dev/null
@@ -1,269 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// cfi_assembler.h: Define CFISection, a class for creating properly
-// (and improperly) formatted DWARF CFI data for unit tests.
-
-#ifndef PROCESSOR_CFI_ASSEMBLER_H_
-#define PROCESSOR_CFI_ASSEMBLER_H_
-
-#include <string>
-
-#include "common/dwarf/dwarf2enums.h"
-#include "common/test_assembler.h"
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-
-using dwarf2reader::DwarfPointerEncoding;
-using google_breakpad::test_assembler::Endianness;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::Section;
-
-class CFISection: public Section {
- public:
-
- // CFI augmentation strings beginning with 'z', defined by the
- // Linux/IA-64 C++ ABI, can specify interesting encodings for
- // addresses appearing in FDE headers and call frame instructions (and
- // for additional fields whose presence the augmentation string
- // specifies). In particular, pointers can be specified to be relative
- // to various base address: the start of the .text section, the
- // location holding the address itself, and so on. These allow the
- // frame data to be position-independent even when they live in
- // write-protected pages. These variants are specified at the
- // following two URLs:
- //
- // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
- // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
- //
- // CFISection leaves the production of well-formed 'z'-augmented CIEs and
- // FDEs to the user, but does provide EncodedPointer, to emit
- // properly-encoded addresses for a given pointer encoding.
- // EncodedPointer uses an instance of this structure to find the base
- // addresses it should use; you can establish a default for all encoded
- // pointers appended to this section with SetEncodedPointerBases.
- struct EncodedPointerBases {
- EncodedPointerBases() : cfi(), text(), data() { }
-
- // The starting address of this CFI section in memory, for
- // DW_EH_PE_pcrel. DW_EH_PE_pcrel pointers may only be used in data
- // that has is loaded into the program's address space.
- uint64_t cfi;
-
- // The starting address of this file's .text section, for DW_EH_PE_textrel.
- uint64_t text;
-
- // The starting address of this file's .got or .eh_frame_hdr section,
- // for DW_EH_PE_datarel.
- uint64_t data;
- };
-
- // Create a CFISection whose endianness is ENDIANNESS, and where
- // machine addresses are ADDRESS_SIZE bytes long. If EH_FRAME is
- // true, use the .eh_frame format, as described by the Linux
- // Standards Base Core Specification, instead of the DWARF CFI
- // format.
- CFISection(Endianness endianness, size_t address_size,
- bool eh_frame = false)
- : Section(endianness), address_size_(address_size), eh_frame_(eh_frame),
- pointer_encoding_(dwarf2reader::DW_EH_PE_absptr),
- encoded_pointer_bases_(), entry_length_(NULL), in_fde_(false) {
- // The 'start', 'Here', and 'Mark' members of a CFISection all refer
- // to section offsets.
- start() = 0;
- }
-
- // Return this CFISection's address size.
- size_t AddressSize() const { return address_size_; }
-
- // Return true if this CFISection uses the .eh_frame format, or
- // false if it contains ordinary DWARF CFI data.
- bool ContainsEHFrame() const { return eh_frame_; }
-
- // Use ENCODING for pointers in calls to FDEHeader and EncodedPointer.
- void SetPointerEncoding(DwarfPointerEncoding encoding) {
- pointer_encoding_ = encoding;
- }
-
- // Use the addresses in BASES as the base addresses for encoded
- // pointers in subsequent calls to FDEHeader or EncodedPointer.
- // This function makes a copy of BASES.
- void SetEncodedPointerBases(const EncodedPointerBases &bases) {
- encoded_pointer_bases_ = bases;
- }
-
- // Append a Common Information Entry header to this section with the
- // given values. If dwarf64 is true, use the 64-bit DWARF initial
- // length format for the CIE's initial length. Return a reference to
- // this section. You should call FinishEntry after writing the last
- // instruction for the CIE.
- //
- // Before calling this function, you will typically want to use Mark
- // or Here to make a label to pass to FDEHeader that refers to this
- // CIE's position in the section.
- CFISection &CIEHeader(uint64_t code_alignment_factor,
- int data_alignment_factor,
- unsigned return_address_register,
- uint8_t version = 3,
- const string &augmentation = "",
- bool dwarf64 = false);
-
- // Append a Frame Description Entry header to this section with the
- // given values. If dwarf64 is true, use the 64-bit DWARF initial
- // length format for the CIE's initial length. Return a reference to
- // this section. You should call FinishEntry after writing the last
- // instruction for the CIE.
- //
- // This function doesn't support entries that are longer than
- // 0xffffff00 bytes. (The "initial length" is always a 32-bit
- // value.) Nor does it support .debug_frame sections longer than
- // 0xffffff00 bytes.
- CFISection &FDEHeader(Label cie_pointer,
- uint64_t initial_location,
- uint64_t address_range,
- bool dwarf64 = false);
-
- // Note the current position as the end of the last CIE or FDE we
- // started, after padding with DW_CFA_nops for alignment. This
- // defines the label representing the entry's length, cited in the
- // entry's header. Return a reference to this section.
- CFISection &FinishEntry();
-
- // Append the contents of BLOCK as a DW_FORM_block value: an
- // unsigned LEB128 length, followed by that many bytes of data.
- CFISection &Block(const string &block) {
- ULEB128(block.size());
- Append(block);
- return *this;
- }
-
- // Append ADDRESS to this section, in the appropriate size and
- // endianness. Return a reference to this section.
- CFISection &Address(uint64_t address) {
- Section::Append(endianness(), address_size_, address);
- return *this;
- }
- CFISection &Address(Label address) {
- Section::Append(endianness(), address_size_, address);
- return *this;
- }
-
- // Append ADDRESS to this section, using ENCODING and BASES. ENCODING
- // defaults to this section's default encoding, established by
- // SetPointerEncoding. BASES defaults to this section's bases, set by
- // SetEncodedPointerBases. If the DW_EH_PE_indirect bit is set in the
- // encoding, assume that ADDRESS is where the true address is stored.
- // Return a reference to this section.
- //
- // (C++ doesn't let me use default arguments here, because I want to
- // refer to members of *this in the default argument expression.)
- CFISection &EncodedPointer(uint64_t address) {
- return EncodedPointer(address, pointer_encoding_, encoded_pointer_bases_);
- }
- CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding) {
- return EncodedPointer(address, encoding, encoded_pointer_bases_);
- }
- CFISection &EncodedPointer(uint64_t address, DwarfPointerEncoding encoding,
- const EncodedPointerBases &bases);
-
- // Restate some member functions, to keep chaining working nicely.
- CFISection &Mark(Label *label) { Section::Mark(label); return *this; }
- CFISection &D8(uint8_t v) { Section::D8(v); return *this; }
- CFISection &D16(uint16_t v) { Section::D16(v); return *this; }
- CFISection &D16(Label v) { Section::D16(v); return *this; }
- CFISection &D32(uint32_t v) { Section::D32(v); return *this; }
- CFISection &D32(const Label &v) { Section::D32(v); return *this; }
- CFISection &D64(uint64_t v) { Section::D64(v); return *this; }
- CFISection &D64(const Label &v) { Section::D64(v); return *this; }
- CFISection &LEB128(long long v) { Section::LEB128(v); return *this; }
- CFISection &ULEB128(uint64_t v) { Section::ULEB128(v); return *this; }
-
- private:
- // A length value that we've appended to the section, but is not yet
- // known. LENGTH is the appended value; START is a label referring
- // to the start of the data whose length was cited.
- struct PendingLength {
- Label length;
- Label start;
- };
-
- // Constants used in CFI/.eh_frame data:
-
- // If the first four bytes of an "initial length" are this constant, then
- // the data uses the 64-bit DWARF format, and the length itself is the
- // subsequent eight bytes.
- static const uint32_t kDwarf64InitialLengthMarker = 0xffffffffU;
-
- // The CIE identifier for 32- and 64-bit DWARF CFI and .eh_frame data.
- static const uint32_t kDwarf32CIEIdentifier = ~(uint32_t)0;
- static const uint64_t kDwarf64CIEIdentifier = ~(uint64_t)0;
- static const uint32_t kEHFrame32CIEIdentifier = 0;
- static const uint64_t kEHFrame64CIEIdentifier = 0;
-
- // The size of a machine address for the data in this section.
- size_t address_size_;
-
- // If true, we are generating a Linux .eh_frame section, instead of
- // a standard DWARF .debug_frame section.
- bool eh_frame_;
-
- // The encoding to use for FDE pointers.
- DwarfPointerEncoding pointer_encoding_;
-
- // The base addresses to use when emitting encoded pointers.
- EncodedPointerBases encoded_pointer_bases_;
-
- // The length value for the current entry.
- //
- // Oddly, this must be dynamically allocated. Labels never get new
- // values; they only acquire constraints on the value they already
- // have, or assert if you assign them something incompatible. So
- // each header needs truly fresh Label objects to cite in their
- // headers and track their positions. The alternative is explicit
- // destructor invocation and a placement new. Ick.
- PendingLength *entry_length_;
-
- // True if we are currently emitting an FDE --- that is, we have
- // called FDEHeader but have not yet called FinishEntry.
- bool in_fde_;
-
- // If in_fde_ is true, this is its starting address. We use this for
- // emitting DW_EH_PE_funcrel pointers.
- uint64_t fde_start_address_;
-};
-
-} // namespace google_breakpad
-
-#endif // PROCESSOR_CFI_ASSEMBLER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc
deleted file mode 100644
index 94542b5ea..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2diehandler.cc: Implement the dwarf2reader::DieDispatcher class.
-// See dwarf2diehandler.h for details.
-
-#include <assert.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "common/dwarf/dwarf2diehandler.h"
-#include "common/using_std_string.h"
-
-namespace dwarf2reader {
-
-DIEDispatcher::~DIEDispatcher() {
- while (!die_handlers_.empty()) {
- HandlerStack &entry = die_handlers_.top();
- if (entry.handler_ != root_handler_)
- delete entry.handler_;
- die_handlers_.pop();
- }
-}
-
-bool DIEDispatcher::StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version) {
- return root_handler_->StartCompilationUnit(offset, address_size,
- offset_size, cu_length,
- dwarf_version);
-}
-
-bool DIEDispatcher::StartDIE(uint64 offset, enum DwarfTag tag) {
- // The stack entry for the parent of this DIE, if there is one.
- HandlerStack *parent = die_handlers_.empty() ? NULL : &die_handlers_.top();
-
- // Does this call indicate that we're done receiving the parent's
- // attributes' values? If so, call its EndAttributes member function.
- if (parent && parent->handler_ && !parent->reported_attributes_end_) {
- parent->reported_attributes_end_ = true;
- if (!parent->handler_->EndAttributes()) {
- // Finish off this handler now. and edit *PARENT to indicate that
- // we don't want to visit any of the children.
- parent->handler_->Finish();
- if (parent->handler_ != root_handler_)
- delete parent->handler_;
- parent->handler_ = NULL;
- return false;
- }
- }
-
- // Find a handler for this DIE.
- DIEHandler *handler;
- if (parent) {
- if (parent->handler_)
- // Ask the parent to find a handler.
- handler = parent->handler_->FindChildHandler(offset, tag);
- else
- // No parent handler means we're not interested in any of our
- // children.
- handler = NULL;
- } else {
- // This is the root DIE. For a non-root DIE, the parent's handler
- // decides whether to visit it, but the root DIE has no parent
- // handler, so we have a special method on the root DIE handler
- // itself to decide.
- if (root_handler_->StartRootDIE(offset, tag))
- handler = root_handler_;
- else
- handler = NULL;
- }
-
- // Push a handler stack entry for this new handler. As an
- // optimization, we don't push NULL-handler entries on top of other
- // NULL-handler entries; we just let the oldest such entry stand for
- // the whole subtree.
- if (handler || !parent || parent->handler_) {
- HandlerStack entry;
- entry.offset_ = offset;
- entry.handler_ = handler;
- entry.reported_attributes_end_ = false;
- die_handlers_.push(entry);
- }
-
- return handler != NULL;
-}
-
-void DIEDispatcher::EndDIE(uint64 offset) {
- assert(!die_handlers_.empty());
- HandlerStack *entry = &die_handlers_.top();
- if (entry->handler_) {
- // This entry had better be the handler for this DIE.
- assert(entry->offset_ == offset);
- // If a DIE has no children, this EndDIE call indicates that we're
- // done receiving its attributes' values.
- if (!entry->reported_attributes_end_)
- entry->handler_->EndAttributes(); // Ignore return value: no children.
- entry->handler_->Finish();
- if (entry->handler_ != root_handler_)
- delete entry->handler_;
- } else {
- // If this DIE is within a tree we're ignoring, then don't pop the
- // handler stack: that entry stands for the whole tree.
- if (entry->offset_ != offset)
- return;
- }
- die_handlers_.pop();
-}
-
-void DIEDispatcher::ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeUnsigned(attr, form, data);
-}
-
-void DIEDispatcher::ProcessAttributeSigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeSigned(attr, form, data);
-}
-
-void DIEDispatcher::ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeReference(attr, form, data);
-}
-
-void DIEDispatcher::ProcessAttributeBuffer(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t *data,
- uint64 len) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeBuffer(attr, form, data, len);
-}
-
-void DIEDispatcher::ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string& data) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeString(attr, form, data);
-}
-
-void DIEDispatcher::ProcessAttributeSignature(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 signature) {
- HandlerStack &current = die_handlers_.top();
- // This had better be an attribute of the DIE we were meant to handle.
- assert(offset == current.offset_);
- current.handler_->ProcessAttributeSignature(attr, form, signature);
-}
-
-} // namespace dwarf2reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h
deleted file mode 100644
index a1e589a86..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler.h
+++ /dev/null
@@ -1,365 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2reader::CompilationUnit is a simple and direct parser for
-// DWARF data, but its handler interface is not convenient to use. In
-// particular:
-//
-// - CompilationUnit calls Dwarf2Handler's member functions to report
-// every attribute's value, regardless of what sort of DIE it is.
-// As a result, the ProcessAttributeX functions end up looking like
-// this:
-//
-// switch (parent_die_tag) {
-// case DW_TAG_x:
-// switch (attribute_name) {
-// case DW_AT_y:
-// handle attribute y of DIE type x
-// ...
-// } break;
-// ...
-// }
-//
-// In C++ it's much nicer to use virtual function dispatch to find
-// the right code for a given case than to switch on the DIE tag
-// like this.
-//
-// - Processing different kinds of DIEs requires different sets of
-// data: lexical block DIEs have start and end addresses, but struct
-// type DIEs don't. It would be nice to be able to have separate
-// handler classes for separate kinds of DIEs, each with the members
-// appropriate to its role, instead of having one handler class that
-// needs to hold data for every DIE type.
-//
-// - There should be a separate instance of the appropriate handler
-// class for each DIE, instead of a single object with tables
-// tracking all the dies in the compilation unit.
-//
-// - It's not convenient to take some action after all a DIE's
-// attributes have been seen, but before visiting any of its
-// children. The only indication you have that a DIE's attribute
-// list is complete is that you get either a StartDIE or an EndDIE
-// call.
-//
-// - It's not convenient to make use of the tree structure of the
-// DIEs. Skipping all the children of a given die requires
-// maintaining state and returning false from StartDIE until we get
-// an EndDIE call with the appropriate offset.
-//
-// This interface tries to take care of all that. (You're shocked, I'm sure.)
-//
-// Using the classes here, you provide an initial handler for the root
-// DIE of the compilation unit. Each handler receives its DIE's
-// attributes, and provides fresh handler objects for children of
-// interest, if any. The three classes are:
-//
-// - DIEHandler: the base class for your DIE-type-specific handler
-// classes.
-//
-// - RootDIEHandler: derived from DIEHandler, the base class for your
-// root DIE handler class.
-//
-// - DIEDispatcher: derived from Dwarf2Handler, an instance of this
-// invokes your DIE-type-specific handler objects.
-//
-// In detail:
-//
-// - Define handler classes specialized for the DIE types you're
-// interested in. These handler classes must inherit from
-// DIEHandler. Thus:
-//
-// class My_DW_TAG_X_Handler: public DIEHandler { ... };
-// class My_DW_TAG_Y_Handler: public DIEHandler { ... };
-//
-// DIEHandler subclasses needn't correspond exactly to single DIE
-// types, as shown here; the point is that you can have several
-// different classes appropriate to different kinds of DIEs.
-//
-// - In particular, define a handler class for the compilation
-// unit's root DIE, that inherits from RootDIEHandler:
-//
-// class My_DW_TAG_compile_unit_Handler: public RootDIEHandler { ... };
-//
-// RootDIEHandler inherits from DIEHandler, adding a few additional
-// member functions for examining the compilation unit as a whole,
-// and other quirks of rootness.
-//
-// - Then, create a DIEDispatcher instance, passing it an instance of
-// your root DIE handler class, and use that DIEDispatcher as the
-// dwarf2reader::CompilationUnit's handler:
-//
-// My_DW_TAG_compile_unit_Handler root_die_handler(...);
-// DIEDispatcher die_dispatcher(&root_die_handler);
-// CompilationUnit reader(sections, offset, bytereader, &die_dispatcher);
-//
-// Here, 'die_dispatcher' acts as a shim between 'reader' and the
-// various DIE-specific handlers you have defined.
-//
-// - When you call reader.Start(), die_dispatcher behaves as follows,
-// starting with your root die handler and the compilation unit's
-// root DIE:
-//
-// - It calls the handler's ProcessAttributeX member functions for
-// each of the DIE's attributes.
-//
-// - It calls the handler's EndAttributes member function. This
-// should return true if any of the DIE's children should be
-// visited, in which case:
-//
-// - For each of the DIE's children, die_dispatcher calls the
-// DIE's handler's FindChildHandler member function. If that
-// returns a pointer to a DIEHandler instance, then
-// die_dispatcher uses that handler to process the child, using
-// this procedure recursively. Alternatively, if
-// FindChildHandler returns NULL, die_dispatcher ignores that
-// child and its descendants.
-//
-// - When die_dispatcher has finished processing all the DIE's
-// children, it invokes the handler's Finish() member function,
-// and destroys the handler. (As a special case, it doesn't
-// destroy the root DIE handler.)
-//
-// This allows the code for handling a particular kind of DIE to be
-// gathered together in a single class, makes it easy to skip all the
-// children or individual children of a particular DIE, and provides
-// appropriate parental context for each die.
-
-#ifndef COMMON_DWARF_DWARF2DIEHANDLER_H__
-#define COMMON_DWARF_DWARF2DIEHANDLER_H__
-
-#include <stdint.h>
-
-#include <stack>
-#include <string>
-
-#include "common/dwarf/types.h"
-#include "common/dwarf/dwarf2enums.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-
-namespace dwarf2reader {
-
-// A base class for handlers for specific DIE types. The series of
-// calls made on a DIE handler is as follows:
-//
-// - for each attribute of the DIE:
-// - ProcessAttributeX()
-// - EndAttributes()
-// - if that returned true, then for each child:
-// - FindChildHandler()
-// - if that returns a non-NULL pointer to a new handler:
-// - recurse, with the new handler and the child die
-// - Finish()
-// - destruction
-class DIEHandler {
- public:
- DIEHandler() { }
- virtual ~DIEHandler() { }
-
- // When we visit a DIE, we first use these member functions to
- // report the DIE's attributes and their values. These have the
- // same restrictions as the corresponding member functions of
- // dwarf2reader::Dwarf2Handler.
- //
- // Since DWARF does not specify in what order attributes must
- // appear, avoid making decisions in these functions that would be
- // affected by the presence of other attributes. The EndAttributes
- // function is a more appropriate place for such work, as all the
- // DIE's attributes have been seen at that point.
- //
- // The default definitions ignore the values they are passed.
- virtual void ProcessAttributeUnsigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) { }
- virtual void ProcessAttributeSigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) { }
- virtual void ProcessAttributeReference(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) { }
- virtual void ProcessAttributeBuffer(enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t *data,
- uint64 len) { }
- virtual void ProcessAttributeString(enum DwarfAttribute attr,
- enum DwarfForm form,
- const string& data) { }
- virtual void ProcessAttributeSignature(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 signture) { }
-
- // Once we have reported all the DIE's attributes' values, we call
- // this member function. If it returns false, we skip all the DIE's
- // children. If it returns true, we call FindChildHandler on each
- // child. If that returns a handler object, we use that to visit
- // the child; otherwise, we skip the child.
- //
- // This is a good place to make decisions that depend on more than
- // one attribute. DWARF does not specify in what order attributes
- // must appear, so only when the EndAttributes function is called
- // does the handler have a complete picture of the DIE's attributes.
- //
- // The default definition elects to ignore the DIE's children.
- // You'll need to override this if you override FindChildHandler,
- // but at least the default behavior isn't to pass the children to
- // FindChildHandler, which then ignores them all.
- virtual bool EndAttributes() { return false; }
-
- // If EndAttributes returns true to indicate that some of the DIE's
- // children might be of interest, then we apply this function to
- // each of the DIE's children. If it returns a handler object, then
- // we use that to visit the child DIE. If it returns NULL, we skip
- // that child DIE (and all its descendants).
- //
- // OFFSET is the offset of the child; TAG indicates what kind of DIE
- // it is.
- //
- // The default definition skips all children.
- virtual DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag) {
- return NULL;
- }
-
- // When we are done processing a DIE, we call this member function.
- // This happens after the EndAttributes call, all FindChildHandler
- // calls (if any), and all operations on the children themselves (if
- // any). We call Finish on every handler --- even if EndAttributes
- // returns false.
- virtual void Finish() { };
-};
-
-// A subclass of DIEHandler, with additional kludges for handling the
-// compilation unit's root die.
-class RootDIEHandler: public DIEHandler {
- public:
- RootDIEHandler() { }
- virtual ~RootDIEHandler() { }
-
- // We pass the values reported via Dwarf2Handler::StartCompilationUnit
- // to this member function, and skip the entire compilation unit if it
- // returns false. So the root DIE handler is actually also
- // responsible for handling the compilation unit metadata.
- // The default definition always visits the compilation unit.
- virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version) { return true; }
-
- // For the root DIE handler only, we pass the offset, tag and
- // attributes of the compilation unit's root DIE. This is the only
- // way the root DIE handler can find the root DIE's tag. If this
- // function returns true, we will visit the root DIE using the usual
- // DIEHandler methods; otherwise, we skip the entire compilation
- // unit.
- //
- // The default definition elects to visit the root DIE.
- virtual bool StartRootDIE(uint64 offset, enum DwarfTag tag) { return true; }
-};
-
-class DIEDispatcher: public Dwarf2Handler {
- public:
- // Create a Dwarf2Handler which uses ROOT_HANDLER as the handler for
- // the compilation unit's root die, as described for the DIEHandler
- // class.
- DIEDispatcher(RootDIEHandler *root_handler) : root_handler_(root_handler) { }
- // Destroying a DIEDispatcher destroys all active handler objects
- // except the root handler.
- ~DIEDispatcher();
- bool StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version);
- bool StartDIE(uint64 offset, enum DwarfTag tag);
- void ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
- void ProcessAttributeSigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data);
- void ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
- void ProcessAttributeBuffer(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t *data,
- uint64 len);
- void ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data);
- void ProcessAttributeSignature(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 signature);
- void EndDIE(uint64 offset);
-
- private:
-
- // The type of a handler stack entry. This includes some fields
- // which don't really need to be on the stack --- they could just be
- // single data members of DIEDispatcher --- but putting them here
- // makes it easier to see that the code is correct.
- struct HandlerStack {
- // The offset of the DIE for this handler stack entry.
- uint64 offset_;
-
- // The handler object interested in this DIE's attributes and
- // children. If NULL, we're not interested in either.
- DIEHandler *handler_;
-
- // Have we reported the end of this DIE's attributes to the handler?
- bool reported_attributes_end_;
- };
-
- // Stack of DIE attribute handlers. At StartDIE(D), the top of the
- // stack is the handler of D's parent, whom we may ask for a handler
- // for D itself. At EndDIE(D), the top of the stack is D's handler.
- // Special cases:
- //
- // - Before we've seen the compilation unit's root DIE, the stack is
- // empty; we'll call root_handler_'s special member functions, and
- // perhaps push root_handler_ on the stack to look at the root's
- // immediate children.
- //
- // - When we decide to ignore a subtree, we only push an entry on
- // the stack for the root of the tree being ignored, rather than
- // pushing lots of stack entries with handler_ set to NULL.
- std::stack<HandlerStack> die_handlers_;
-
- // The root handler. We don't push it on die_handlers_ until we
- // actually get the StartDIE call for the root.
- RootDIEHandler *root_handler_;
-};
-
-} // namespace dwarf2reader
-#endif // COMMON_DWARF_DWARF2DIEHANDLER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler_unittest.cc
deleted file mode 100644
index db70eb31b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2diehandler_unittest.cc
+++ /dev/null
@@ -1,527 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2diehander_unittest.cc: Unit tests for google_breakpad::DIEDispatcher.
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-
-#include "breakpad_googletest_includes.h"
-
-#include "common/dwarf/dwarf2diehandler.h"
-#include "common/using_std_string.h"
-
-using std::make_pair;
-
-using ::testing::_;
-using ::testing::ContainerEq;
-using ::testing::ElementsAreArray;
-using ::testing::Eq;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::Sequence;
-using ::testing::StrEq;
-
-using dwarf2reader::DIEDispatcher;
-using dwarf2reader::DIEHandler;
-using dwarf2reader::DwarfAttribute;
-using dwarf2reader::DwarfForm;
-using dwarf2reader::DwarfTag;
-using dwarf2reader::RootDIEHandler;
-
-class MockDIEHandler: public DIEHandler {
- public:
- MOCK_METHOD3(ProcessAttributeUnsigned,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD3(ProcessAttributeSigned,
- void(DwarfAttribute, DwarfForm, int64));
- MOCK_METHOD3(ProcessAttributeReference,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD4(ProcessAttributeBuffer,
- void(DwarfAttribute, DwarfForm, const uint8_t *, uint64));
- MOCK_METHOD3(ProcessAttributeString,
- void(DwarfAttribute, DwarfForm, const string &));
- MOCK_METHOD3(ProcessAttributeSignature,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD0(EndAttributes, bool());
- MOCK_METHOD2(FindChildHandler, DIEHandler *(uint64, DwarfTag));
- MOCK_METHOD0(Finish, void());
-};
-
-class MockRootDIEHandler: public RootDIEHandler {
- public:
- MOCK_METHOD3(ProcessAttributeUnsigned,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD3(ProcessAttributeSigned,
- void(DwarfAttribute, DwarfForm, int64));
- MOCK_METHOD3(ProcessAttributeReference,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD4(ProcessAttributeBuffer,
- void(DwarfAttribute, DwarfForm, const uint8_t *, uint64));
- MOCK_METHOD3(ProcessAttributeString,
- void(DwarfAttribute, DwarfForm, const string &));
- MOCK_METHOD3(ProcessAttributeSignature,
- void(DwarfAttribute, DwarfForm, uint64));
- MOCK_METHOD0(EndAttributes, bool());
- MOCK_METHOD2(FindChildHandler, DIEHandler *(uint64, DwarfTag));
- MOCK_METHOD0(Finish, void());
- MOCK_METHOD5(StartCompilationUnit, bool(uint64, uint8, uint8, uint64, uint8));
- MOCK_METHOD2(StartRootDIE, bool(uint64, DwarfTag));
-};
-
-// If the handler elects to skip the compilation unit, the dispatcher
-// should tell the reader so.
-TEST(Dwarf2DIEHandler, SkipCompilationUnit) {
- Sequence s;
- MockRootDIEHandler mock_root_handler;
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0x8d42aed77cfccf3eLL,
- 0x89, 0xdc,
- 0x2ecb4dc778a80f21LL,
- 0x66))
- .InSequence(s)
- .WillOnce(Return(false));
-
- EXPECT_FALSE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL,
- 0x89, 0xdc,
- 0x2ecb4dc778a80f21LL,
- 0x66));
-}
-
-// If the handler elects to skip the root DIE, the dispatcher should
-// tell the reader so.
-TEST(Dwarf2DIEHandler, SkipRootDIE) {
- Sequence s;
- MockRootDIEHandler mock_root_handler;
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0xde8994029fc8b999LL, 0xf4, 0x02,
- 0xb00febffa76e2b2bLL, 0x5c))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(mock_root_handler,
- StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6))
- .InSequence(s)
- .WillOnce(Return(false));
-
- EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0xde8994029fc8b999LL,
- 0xf4, 0x02,
- 0xb00febffa76e2b2bLL, 0x5c));
- EXPECT_FALSE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL,
- (DwarfTag) 0xb4f98da6));
- die_dispatcher.EndDIE(0x7d08242b4b510cf2LL);
-}
-
-// If the handler elects to skip the root DIE's children, the
-// dispatcher should tell the reader so --- and avoid deleting the
-// root handler.
-TEST(Dwarf2DIEHandler, SkipRootDIEChildren) {
- MockRootDIEHandler mock_root_handler;
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- {
- InSequence s;
-
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0x15d6897480cc65a7LL, 0x26, 0xa0,
- 0x09f8bf0767f91675LL, 0xdb))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_root_handler,
- StartRootDIE(0x7d08242b4b510cf2LL, (DwarfTag) 0xb4f98da6))
- .WillOnce(Return(true));
- // Please don't tell me about my children.
- EXPECT_CALL(mock_root_handler, EndAttributes())
- .WillOnce(Return(false));
- EXPECT_CALL(mock_root_handler, Finish())
- .WillOnce(Return());
- }
-
- EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x15d6897480cc65a7LL,
- 0x26, 0xa0,
- 0x09f8bf0767f91675LL, 0xdb));
- EXPECT_TRUE(die_dispatcher.StartDIE(0x7d08242b4b510cf2LL,
- (DwarfTag) 0xb4f98da6));
- EXPECT_FALSE(die_dispatcher.StartDIE(0x435150ceedccda18LL,
- (DwarfTag) 0xc3a17bba));
- die_dispatcher.EndDIE(0x435150ceedccda18LL);
- die_dispatcher.EndDIE(0x7d08242b4b510cf2LL);
-}
-
-// The dispatcher should pass attribute values through to the die
-// handler accurately.
-TEST(Dwarf2DIEHandler, PassAttributeValues) {
- MockRootDIEHandler mock_root_handler;
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- const uint8_t buffer[10] = {
- 0x24, 0x24, 0x35, 0x9a, 0xca, 0xcf, 0xa8, 0x84, 0xa7, 0x18
- };
- string str = "\xc8\x26\x2e\x0d\xa4\x9c\x37\xd6\xfb\x1d";
-
- // Set expectations.
- {
- InSequence s;
-
- // We'll like the compilation unit header.
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0x8d42aed77cfccf3eLL, 0x89, 0xdc,
- 0x2ecb4dc778a80f21LL, 0x66))
- .WillOnce(Return(true));
-
- // We'll like the root DIE.
- EXPECT_CALL(mock_root_handler,
- StartRootDIE(0xe2222da01e29f2a9LL, (DwarfTag) 0x9829445c))
- .WillOnce(Return(true));
-
- // Expect some attribute values.
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeUnsigned((DwarfAttribute) 0x1cc0bfed,
- (DwarfForm) 0x424f1468,
- 0xa592571997facda1ULL))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeSigned((DwarfAttribute) 0x43694dc9,
- (DwarfForm) 0xf6f78901L,
- 0x92602a4e3bf1f446LL))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeReference((DwarfAttribute) 0x4033e8cL,
- (DwarfForm) 0xf66fbe0bL,
- 0x50fddef44734fdecULL))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeBuffer((DwarfAttribute) 0x25d7e0af,
- (DwarfForm) 0xe99a539a,
- buffer, sizeof(buffer)))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeString((DwarfAttribute) 0x310ed065,
- (DwarfForm) 0x15762fec,
- StrEq(str)))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeSignature((DwarfAttribute) 0x58790d72,
- (DwarfForm) 0x4159f138,
- 0x94682463613e6a5fULL))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler, EndAttributes())
- .WillOnce(Return(true));
- EXPECT_CALL(mock_root_handler, FindChildHandler(_, _))
- .Times(0);
- EXPECT_CALL(mock_root_handler, Finish())
- .WillOnce(Return());
- }
-
- // Drive the dispatcher.
-
- // Report the CU header.
- EXPECT_TRUE(die_dispatcher.StartCompilationUnit(0x8d42aed77cfccf3eLL,
- 0x89, 0xdc,
- 0x2ecb4dc778a80f21LL,
- 0x66));
- // Report the root DIE.
- EXPECT_TRUE(die_dispatcher.StartDIE(0xe2222da01e29f2a9LL,
- (DwarfTag) 0x9829445c));
-
- // Report some attribute values.
- die_dispatcher.ProcessAttributeUnsigned(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x1cc0bfed,
- (DwarfForm) 0x424f1468,
- 0xa592571997facda1ULL);
- die_dispatcher.ProcessAttributeSigned(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x43694dc9,
- (DwarfForm) 0xf6f78901,
- 0x92602a4e3bf1f446LL);
- die_dispatcher.ProcessAttributeReference(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x4033e8c,
- (DwarfForm) 0xf66fbe0b,
- 0x50fddef44734fdecULL);
- die_dispatcher.ProcessAttributeBuffer(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x25d7e0af,
- (DwarfForm) 0xe99a539a,
- buffer, sizeof(buffer));
- die_dispatcher.ProcessAttributeString(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x310ed065,
- (DwarfForm) 0x15762fec,
- str);
- die_dispatcher.ProcessAttributeSignature(0xe2222da01e29f2a9LL,
- (DwarfAttribute) 0x58790d72,
- (DwarfForm) 0x4159f138,
- 0x94682463613e6a5fULL);
-
- // Finish the root DIE (and thus the CU).
- die_dispatcher.EndDIE(0xe2222da01e29f2a9LL);
-}
-
-TEST(Dwarf2DIEHandler, FindAndSkipChildren) {
- MockRootDIEHandler mock_root_handler;
- MockDIEHandler *mock_child1_handler = new(MockDIEHandler);
- MockDIEHandler *mock_child3_handler = new(MockDIEHandler);
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- {
- InSequence s;
-
- // We'll like the compilation unit header.
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21,
- 0x47dd3c764275a216LL, 0xa5))
- .WillOnce(Return(true));
-
- // Root DIE.
- {
- EXPECT_CALL(mock_root_handler,
- StartRootDIE(0x15f0e06bdfe3c372LL, (DwarfTag) 0xf5d60c59))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_root_handler,
- ProcessAttributeSigned((DwarfAttribute) 0xf779a642,
- (DwarfForm) 0x2cb63027,
- 0x18e744661769d08fLL))
- .WillOnce(Return());
- EXPECT_CALL(mock_root_handler, EndAttributes())
- .WillOnce(Return(true));
-
- // First child DIE.
- EXPECT_CALL(mock_root_handler,
- FindChildHandler(0x149f644f8116fe8cLL,
- (DwarfTag) 0xac2cbd8c))
- .WillOnce(Return(mock_child1_handler));
- {
- EXPECT_CALL(*mock_child1_handler,
- ProcessAttributeSigned((DwarfAttribute) 0xa6fd6f65,
- (DwarfForm) 0xe4f64c41,
- 0x1b04e5444a55fe67LL))
- .WillOnce(Return());
- EXPECT_CALL(*mock_child1_handler, EndAttributes())
- .WillOnce(Return(false));
- // Skip first grandchild DIE and first great-grandchild DIE.
- EXPECT_CALL(*mock_child1_handler, Finish())
- .WillOnce(Return());
- }
-
- // Second child DIE. Root handler will decline to return a handler
- // for this child.
- EXPECT_CALL(mock_root_handler,
- FindChildHandler(0x97412be24875de9dLL,
- (DwarfTag) 0x505a068b))
- .WillOnce(Return((DIEHandler *) NULL));
-
- // Third child DIE.
- EXPECT_CALL(mock_root_handler,
- FindChildHandler(0x753c964c8ab538aeLL,
- (DwarfTag) 0x8c22970e))
- .WillOnce(Return(mock_child3_handler));
- {
- EXPECT_CALL(*mock_child3_handler,
- ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb,
- (DwarfForm) 0x610b7ae1,
- 0x3ea5c609d7d7560fLL))
- .WillOnce(Return());
- EXPECT_CALL(*mock_child3_handler, EndAttributes())
- .WillOnce(Return(true));
- EXPECT_CALL(*mock_child3_handler, Finish())
- .WillOnce(Return());
- }
-
- EXPECT_CALL(mock_root_handler, Finish())
- .WillOnce(Return());
- }
- }
-
-
- // Drive the dispatcher.
-
- // Report the CU header.
- EXPECT_TRUE(die_dispatcher
- .StartCompilationUnit(0x9ec1e6d05e434a0eLL, 0xeb, 0x21,
- 0x47dd3c764275a216LL, 0xa5));
- // Report the root DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0x15f0e06bdfe3c372LL,
- (DwarfTag) 0xf5d60c59));
- die_dispatcher.ProcessAttributeSigned(0x15f0e06bdfe3c372LL,
- (DwarfAttribute) 0xf779a642,
- (DwarfForm) 0x2cb63027,
- 0x18e744661769d08fLL);
-
- // First child DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0x149f644f8116fe8cLL,
- (DwarfTag) 0xac2cbd8c));
- die_dispatcher.ProcessAttributeSigned(0x149f644f8116fe8cLL,
- (DwarfAttribute) 0xa6fd6f65,
- (DwarfForm) 0xe4f64c41,
- 0x1b04e5444a55fe67LL);
-
- // First grandchild DIE. Will be skipped.
- {
- EXPECT_FALSE(die_dispatcher.StartDIE(0xd68de1ee0bd29419LL,
- (DwarfTag) 0x22f05a15));
- // First great-grandchild DIE. Will be skipped without being
- // mentioned to any handler.
- {
- EXPECT_FALSE(die_dispatcher
- .StartDIE(0xb3076285d25cac25LL,
- (DwarfTag) 0xcff4061b));
- die_dispatcher.EndDIE(0xb3076285d25cac25LL);
- }
- die_dispatcher.EndDIE(0xd68de1ee0bd29419LL);
- }
- die_dispatcher.EndDIE(0x149f644f8116fe8cLL);
- }
-
- // Second child DIE. Root handler will decline to find a handler for it.
- {
- EXPECT_FALSE(die_dispatcher.StartDIE(0x97412be24875de9dLL,
- (DwarfTag) 0x505a068b));
- die_dispatcher.EndDIE(0x97412be24875de9dLL);
- }
-
- // Third child DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0x753c964c8ab538aeLL,
- (DwarfTag) 0x8c22970e));
- die_dispatcher.ProcessAttributeSigned(0x753c964c8ab538aeLL,
- (DwarfAttribute) 0x4e2b7cfb,
- (DwarfForm) 0x610b7ae1,
- 0x3ea5c609d7d7560fLL);
- die_dispatcher.EndDIE(0x753c964c8ab538aeLL);
- }
-
- // Finish the root DIE (and thus the CU).
- die_dispatcher.EndDIE(0x15f0e06bdfe3c372LL);
- }
-}
-
-// The DIEDispatcher destructor is supposed to delete all handlers on
-// the stack, except for the root.
-TEST(Dwarf2DIEHandler, FreeHandlersOnStack) {
- MockRootDIEHandler mock_root_handler;
- MockDIEHandler *mock_child_handler = new(MockDIEHandler);
- MockDIEHandler *mock_grandchild_handler = new(MockDIEHandler);
-
- {
- InSequence s;
-
- // We'll like the compilation unit header.
- EXPECT_CALL(mock_root_handler,
- StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89,
- 0x76d392ff393ddda2LL, 0xbf))
- .WillOnce(Return(true));
-
- // Root DIE.
- {
- EXPECT_CALL(mock_root_handler,
- StartRootDIE(0xbf13b761691ddc91LL, (DwarfTag) 0x98980361))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_root_handler, EndAttributes())
- .WillOnce(Return(true));
-
- // Child DIE.
- EXPECT_CALL(mock_root_handler,
- FindChildHandler(0x058f09240c5fc8c9LL,
- (DwarfTag) 0x898bf0d0))
- .WillOnce(Return(mock_child_handler));
- {
- EXPECT_CALL(*mock_child_handler, EndAttributes())
- .WillOnce(Return(true));
-
- // Grandchild DIE.
- EXPECT_CALL(*mock_child_handler,
- FindChildHandler(0x32dc00c9945dc0c8LL,
- (DwarfTag) 0x2802d007))
- .WillOnce(Return(mock_grandchild_handler));
- {
- EXPECT_CALL(*mock_grandchild_handler,
- ProcessAttributeSigned((DwarfAttribute) 0x4e2b7cfb,
- (DwarfForm) 0x610b7ae1,
- 0x3ea5c609d7d7560fLL))
- .WillOnce(Return());
-
- // At this point, we abandon the traversal, so none of the
- // usual stuff should get called.
- EXPECT_CALL(*mock_grandchild_handler, EndAttributes())
- .Times(0);
- EXPECT_CALL(*mock_grandchild_handler, Finish())
- .Times(0);
- }
-
- EXPECT_CALL(*mock_child_handler, Finish())
- .Times(0);
- }
-
- EXPECT_CALL(mock_root_handler, Finish())
- .Times(0);
- }
- }
-
- // The dispatcher.
- DIEDispatcher die_dispatcher(&mock_root_handler);
-
- // Report the CU header.
- EXPECT_TRUE(die_dispatcher
- .StartCompilationUnit(0x87b41ba8381cd71cLL, 0xff, 0x89,
- 0x76d392ff393ddda2LL, 0xbf));
- // Report the root DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0xbf13b761691ddc91LL,
- (DwarfTag) 0x98980361));
-
- // Child DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0x058f09240c5fc8c9LL,
- (DwarfTag) 0x898bf0d0));
-
- // Grandchild DIE.
- {
- EXPECT_TRUE(die_dispatcher.StartDIE(0x32dc00c9945dc0c8LL,
- (DwarfTag) 0x2802d007));
- die_dispatcher.ProcessAttributeSigned(0x32dc00c9945dc0c8LL,
- (DwarfAttribute) 0x4e2b7cfb,
- (DwarfForm) 0x610b7ae1,
- 0x3ea5c609d7d7560fLL);
-
- // Stop the traversal abruptly, so that there will still be
- // handlers on the stack when the dispatcher is destructed.
-
- // No EndDIE call...
- }
- // No EndDIE call...
- }
- // No EndDIE call...
- }
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h
deleted file mode 100644
index 6b8a72459..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2enums.h
+++ /dev/null
@@ -1,675 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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 COMMON_DWARF_DWARF2ENUMS_H__
-#define COMMON_DWARF_DWARF2ENUMS_H__
-
-namespace dwarf2reader {
-
-// These enums do not follow the google3 style only because they are
-// known universally (specs, other implementations) by the names in
-// exactly this capitalization.
-// Tag names and codes.
-enum DwarfTag {
- DW_TAG_padding = 0x00,
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_param = 0x2f,
- DW_TAG_template_value_param = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- // DWARF 3.
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- // SGI/MIPS Extensions.
- DW_TAG_MIPS_loop = 0x4081,
- // HP extensions. See:
- // ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz
- DW_TAG_HP_array_descriptor = 0x4090,
- // GNU extensions.
- DW_TAG_format_label = 0x4101, // For FORTRAN 77 and Fortran 90.
- DW_TAG_function_template = 0x4102, // For C++.
- DW_TAG_class_template = 0x4103, // For C++.
- DW_TAG_GNU_BINCL = 0x4104,
- DW_TAG_GNU_EINCL = 0x4105,
- // Extensions for UPC. See: http://upc.gwu.edu/~upc.
- DW_TAG_upc_shared_type = 0x8765,
- DW_TAG_upc_strict_type = 0x8766,
- DW_TAG_upc_relaxed_type = 0x8767,
- // PGI (STMicroelectronics) extensions. No documentation available.
- DW_TAG_PGI_kanji_type = 0xA000,
- DW_TAG_PGI_interface_block = 0xA020
-};
-
-
-enum DwarfHasChild {
- DW_children_no = 0,
- DW_children_yes = 1
-};
-
-// Form names and codes.
-enum DwarfForm {
- DW_FORM_addr = 0x01,
- DW_FORM_block2 = 0x03,
- DW_FORM_block4 = 0x04,
- DW_FORM_data2 = 0x05,
- DW_FORM_data4 = 0x06,
- DW_FORM_data8 = 0x07,
- DW_FORM_string = 0x08,
- DW_FORM_block = 0x09,
- DW_FORM_block1 = 0x0a,
- DW_FORM_data1 = 0x0b,
- DW_FORM_flag = 0x0c,
- DW_FORM_sdata = 0x0d,
- DW_FORM_strp = 0x0e,
- DW_FORM_udata = 0x0f,
- DW_FORM_ref_addr = 0x10,
- DW_FORM_ref1 = 0x11,
- DW_FORM_ref2 = 0x12,
- DW_FORM_ref4 = 0x13,
- DW_FORM_ref8 = 0x14,
- DW_FORM_ref_udata = 0x15,
- DW_FORM_indirect = 0x16,
-
- // Added in DWARF 4:
- DW_FORM_sec_offset = 0x17,
- DW_FORM_exprloc = 0x18,
- DW_FORM_flag_present = 0x19,
- DW_FORM_ref_sig8 = 0x20,
- // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
- DW_FORM_GNU_addr_index = 0x1f01,
- DW_FORM_GNU_str_index = 0x1f02
-};
-
-// Attribute names and codes
-enum DwarfAttribute {
- DW_AT_sibling = 0x01,
- DW_AT_location = 0x02,
- DW_AT_name = 0x03,
- DW_AT_ordering = 0x09,
- DW_AT_subscr_data = 0x0a,
- DW_AT_byte_size = 0x0b,
- DW_AT_bit_offset = 0x0c,
- DW_AT_bit_size = 0x0d,
- DW_AT_element_list = 0x0f,
- DW_AT_stmt_list = 0x10,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
- DW_AT_member = 0x14,
- DW_AT_discr = 0x15,
- DW_AT_discr_value = 0x16,
- DW_AT_visibility = 0x17,
- DW_AT_import = 0x18,
- DW_AT_string_length = 0x19,
- DW_AT_common_reference = 0x1a,
- DW_AT_comp_dir = 0x1b,
- DW_AT_const_value = 0x1c,
- DW_AT_containing_type = 0x1d,
- DW_AT_default_value = 0x1e,
- DW_AT_inline = 0x20,
- DW_AT_is_optional = 0x21,
- DW_AT_lower_bound = 0x22,
- DW_AT_producer = 0x25,
- DW_AT_prototyped = 0x27,
- DW_AT_return_addr = 0x2a,
- DW_AT_start_scope = 0x2c,
- DW_AT_stride_size = 0x2e,
- DW_AT_upper_bound = 0x2f,
- DW_AT_abstract_origin = 0x31,
- DW_AT_accessibility = 0x32,
- DW_AT_address_class = 0x33,
- DW_AT_artificial = 0x34,
- DW_AT_base_types = 0x35,
- DW_AT_calling_convention = 0x36,
- DW_AT_count = 0x37,
- DW_AT_data_member_location = 0x38,
- DW_AT_decl_column = 0x39,
- DW_AT_decl_file = 0x3a,
- DW_AT_decl_line = 0x3b,
- DW_AT_declaration = 0x3c,
- DW_AT_discr_list = 0x3d,
- DW_AT_encoding = 0x3e,
- DW_AT_external = 0x3f,
- DW_AT_frame_base = 0x40,
- DW_AT_friend = 0x41,
- DW_AT_identifier_case = 0x42,
- DW_AT_macro_info = 0x43,
- DW_AT_namelist_items = 0x44,
- DW_AT_priority = 0x45,
- DW_AT_segment = 0x46,
- DW_AT_specification = 0x47,
- DW_AT_static_link = 0x48,
- DW_AT_type = 0x49,
- DW_AT_use_location = 0x4a,
- DW_AT_variable_parameter = 0x4b,
- DW_AT_virtuality = 0x4c,
- DW_AT_vtable_elem_location = 0x4d,
- // DWARF 3 values.
- DW_AT_allocated = 0x4e,
- DW_AT_associated = 0x4f,
- DW_AT_data_location = 0x50,
- DW_AT_stride = 0x51,
- DW_AT_entry_pc = 0x52,
- DW_AT_use_UTF8 = 0x53,
- DW_AT_extension = 0x54,
- DW_AT_ranges = 0x55,
- DW_AT_trampoline = 0x56,
- DW_AT_call_column = 0x57,
- DW_AT_call_file = 0x58,
- DW_AT_call_line = 0x59,
- // SGI/MIPS extensions.
- DW_AT_MIPS_fde = 0x2001,
- DW_AT_MIPS_loop_begin = 0x2002,
- DW_AT_MIPS_tail_loop_begin = 0x2003,
- DW_AT_MIPS_epilog_begin = 0x2004,
- DW_AT_MIPS_loop_unroll_factor = 0x2005,
- DW_AT_MIPS_software_pipeline_depth = 0x2006,
- DW_AT_MIPS_linkage_name = 0x2007,
- DW_AT_MIPS_stride = 0x2008,
- DW_AT_MIPS_abstract_name = 0x2009,
- DW_AT_MIPS_clone_origin = 0x200a,
- DW_AT_MIPS_has_inlines = 0x200b,
- // HP extensions.
- DW_AT_HP_block_index = 0x2000,
- DW_AT_HP_unmodifiable = 0x2001, // Same as DW_AT_MIPS_fde.
- DW_AT_HP_actuals_stmt_list = 0x2010,
- DW_AT_HP_proc_per_section = 0x2011,
- DW_AT_HP_raw_data_ptr = 0x2012,
- DW_AT_HP_pass_by_reference = 0x2013,
- DW_AT_HP_opt_level = 0x2014,
- DW_AT_HP_prof_version_id = 0x2015,
- DW_AT_HP_opt_flags = 0x2016,
- DW_AT_HP_cold_region_low_pc = 0x2017,
- DW_AT_HP_cold_region_high_pc = 0x2018,
- DW_AT_HP_all_variables_modifiable = 0x2019,
- DW_AT_HP_linkage_name = 0x201a,
- DW_AT_HP_prof_flags = 0x201b, // In comp unit of procs_info for -g.
- // GNU extensions.
- DW_AT_sf_names = 0x2101,
- DW_AT_src_info = 0x2102,
- DW_AT_mac_info = 0x2103,
- DW_AT_src_coords = 0x2104,
- DW_AT_body_begin = 0x2105,
- DW_AT_body_end = 0x2106,
- DW_AT_GNU_vector = 0x2107,
- // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
- DW_AT_GNU_dwo_name = 0x2130,
- DW_AT_GNU_dwo_id = 0x2131,
- DW_AT_GNU_ranges_base = 0x2132,
- DW_AT_GNU_addr_base = 0x2133,
- DW_AT_GNU_pubnames = 0x2134,
- DW_AT_GNU_pubtypes = 0x2135,
- // VMS extensions.
- DW_AT_VMS_rtnbeg_pd_address = 0x2201,
- // UPC extension.
- DW_AT_upc_threads_scaled = 0x3210,
- // PGI (STMicroelectronics) extensions.
- DW_AT_PGI_lbase = 0x3a00,
- DW_AT_PGI_soffset = 0x3a01,
- DW_AT_PGI_lstride = 0x3a02
-};
-
-
-// Line number opcodes.
-enum DwarfLineNumberOps {
- DW_LNS_extended_op = 0,
- DW_LNS_copy = 1,
- DW_LNS_advance_pc = 2,
- DW_LNS_advance_line = 3,
- DW_LNS_set_file = 4,
- DW_LNS_set_column = 5,
- DW_LNS_negate_stmt = 6,
- DW_LNS_set_basic_block = 7,
- DW_LNS_const_add_pc = 8,
- DW_LNS_fixed_advance_pc = 9,
- // DWARF 3.
- DW_LNS_set_prologue_end = 10,
- DW_LNS_set_epilogue_begin = 11,
- DW_LNS_set_isa = 12
-};
-
-// Line number extended opcodes.
-enum DwarfLineNumberExtendedOps {
- DW_LNE_end_sequence = 1,
- DW_LNE_set_address = 2,
- DW_LNE_define_file = 3,
- // HP extensions.
- DW_LNE_HP_negate_is_UV_update = 0x11,
- DW_LNE_HP_push_context = 0x12,
- DW_LNE_HP_pop_context = 0x13,
- DW_LNE_HP_set_file_line_column = 0x14,
- DW_LNE_HP_set_routine_name = 0x15,
- DW_LNE_HP_set_sequence = 0x16,
- DW_LNE_HP_negate_post_semantics = 0x17,
- DW_LNE_HP_negate_function_exit = 0x18,
- DW_LNE_HP_negate_front_end_logical = 0x19,
- DW_LNE_HP_define_proc = 0x20
-};
-
-// Type encoding names and codes
-enum DwarfEncoding {
- DW_ATE_address =0x1,
- DW_ATE_boolean =0x2,
- DW_ATE_complex_float =0x3,
- DW_ATE_float =0x4,
- DW_ATE_signed =0x5,
- DW_ATE_signed_char =0x6,
- DW_ATE_unsigned =0x7,
- DW_ATE_unsigned_char =0x8,
- // DWARF3/DWARF3f
- DW_ATE_imaginary_float =0x9,
- DW_ATE_packed_decimal =0xa,
- DW_ATE_numeric_string =0xb,
- DW_ATE_edited =0xc,
- DW_ATE_signed_fixed =0xd,
- DW_ATE_unsigned_fixed =0xe,
- DW_ATE_decimal_float =0xf,
- DW_ATE_lo_user =0x80,
- DW_ATE_hi_user =0xff
-};
-
-// Location virtual machine opcodes
-enum DwarfOpcode {
- DW_OP_addr =0x03,
- DW_OP_deref =0x06,
- DW_OP_const1u =0x08,
- DW_OP_const1s =0x09,
- DW_OP_const2u =0x0a,
- DW_OP_const2s =0x0b,
- DW_OP_const4u =0x0c,
- DW_OP_const4s =0x0d,
- DW_OP_const8u =0x0e,
- DW_OP_const8s =0x0f,
- DW_OP_constu =0x10,
- DW_OP_consts =0x11,
- DW_OP_dup =0x12,
- DW_OP_drop =0x13,
- DW_OP_over =0x14,
- DW_OP_pick =0x15,
- DW_OP_swap =0x16,
- DW_OP_rot =0x17,
- DW_OP_xderef =0x18,
- DW_OP_abs =0x19,
- DW_OP_and =0x1a,
- DW_OP_div =0x1b,
- DW_OP_minus =0x1c,
- DW_OP_mod =0x1d,
- DW_OP_mul =0x1e,
- DW_OP_neg =0x1f,
- DW_OP_not =0x20,
- DW_OP_or =0x21,
- DW_OP_plus =0x22,
- DW_OP_plus_uconst =0x23,
- DW_OP_shl =0x24,
- DW_OP_shr =0x25,
- DW_OP_shra =0x26,
- DW_OP_xor =0x27,
- DW_OP_bra =0x28,
- DW_OP_eq =0x29,
- DW_OP_ge =0x2a,
- DW_OP_gt =0x2b,
- DW_OP_le =0x2c,
- DW_OP_lt =0x2d,
- DW_OP_ne =0x2e,
- DW_OP_skip =0x2f,
- DW_OP_lit0 =0x30,
- DW_OP_lit1 =0x31,
- DW_OP_lit2 =0x32,
- DW_OP_lit3 =0x33,
- DW_OP_lit4 =0x34,
- DW_OP_lit5 =0x35,
- DW_OP_lit6 =0x36,
- DW_OP_lit7 =0x37,
- DW_OP_lit8 =0x38,
- DW_OP_lit9 =0x39,
- DW_OP_lit10 =0x3a,
- DW_OP_lit11 =0x3b,
- DW_OP_lit12 =0x3c,
- DW_OP_lit13 =0x3d,
- DW_OP_lit14 =0x3e,
- DW_OP_lit15 =0x3f,
- DW_OP_lit16 =0x40,
- DW_OP_lit17 =0x41,
- DW_OP_lit18 =0x42,
- DW_OP_lit19 =0x43,
- DW_OP_lit20 =0x44,
- DW_OP_lit21 =0x45,
- DW_OP_lit22 =0x46,
- DW_OP_lit23 =0x47,
- DW_OP_lit24 =0x48,
- DW_OP_lit25 =0x49,
- DW_OP_lit26 =0x4a,
- DW_OP_lit27 =0x4b,
- DW_OP_lit28 =0x4c,
- DW_OP_lit29 =0x4d,
- DW_OP_lit30 =0x4e,
- DW_OP_lit31 =0x4f,
- DW_OP_reg0 =0x50,
- DW_OP_reg1 =0x51,
- DW_OP_reg2 =0x52,
- DW_OP_reg3 =0x53,
- DW_OP_reg4 =0x54,
- DW_OP_reg5 =0x55,
- DW_OP_reg6 =0x56,
- DW_OP_reg7 =0x57,
- DW_OP_reg8 =0x58,
- DW_OP_reg9 =0x59,
- DW_OP_reg10 =0x5a,
- DW_OP_reg11 =0x5b,
- DW_OP_reg12 =0x5c,
- DW_OP_reg13 =0x5d,
- DW_OP_reg14 =0x5e,
- DW_OP_reg15 =0x5f,
- DW_OP_reg16 =0x60,
- DW_OP_reg17 =0x61,
- DW_OP_reg18 =0x62,
- DW_OP_reg19 =0x63,
- DW_OP_reg20 =0x64,
- DW_OP_reg21 =0x65,
- DW_OP_reg22 =0x66,
- DW_OP_reg23 =0x67,
- DW_OP_reg24 =0x68,
- DW_OP_reg25 =0x69,
- DW_OP_reg26 =0x6a,
- DW_OP_reg27 =0x6b,
- DW_OP_reg28 =0x6c,
- DW_OP_reg29 =0x6d,
- DW_OP_reg30 =0x6e,
- DW_OP_reg31 =0x6f,
- DW_OP_breg0 =0x70,
- DW_OP_breg1 =0x71,
- DW_OP_breg2 =0x72,
- DW_OP_breg3 =0x73,
- DW_OP_breg4 =0x74,
- DW_OP_breg5 =0x75,
- DW_OP_breg6 =0x76,
- DW_OP_breg7 =0x77,
- DW_OP_breg8 =0x78,
- DW_OP_breg9 =0x79,
- DW_OP_breg10 =0x7a,
- DW_OP_breg11 =0x7b,
- DW_OP_breg12 =0x7c,
- DW_OP_breg13 =0x7d,
- DW_OP_breg14 =0x7e,
- DW_OP_breg15 =0x7f,
- DW_OP_breg16 =0x80,
- DW_OP_breg17 =0x81,
- DW_OP_breg18 =0x82,
- DW_OP_breg19 =0x83,
- DW_OP_breg20 =0x84,
- DW_OP_breg21 =0x85,
- DW_OP_breg22 =0x86,
- DW_OP_breg23 =0x87,
- DW_OP_breg24 =0x88,
- DW_OP_breg25 =0x89,
- DW_OP_breg26 =0x8a,
- DW_OP_breg27 =0x8b,
- DW_OP_breg28 =0x8c,
- DW_OP_breg29 =0x8d,
- DW_OP_breg30 =0x8e,
- DW_OP_breg31 =0x8f,
- DW_OP_regX =0x90,
- DW_OP_fbreg =0x91,
- DW_OP_bregX =0x92,
- DW_OP_piece =0x93,
- DW_OP_deref_size =0x94,
- DW_OP_xderef_size =0x95,
- DW_OP_nop =0x96,
- // DWARF3/DWARF3f
- DW_OP_push_object_address =0x97,
- DW_OP_call2 =0x98,
- DW_OP_call4 =0x99,
- DW_OP_call_ref =0x9a,
- DW_OP_form_tls_address =0x9b,
- DW_OP_call_frame_cfa =0x9c,
- DW_OP_bit_piece =0x9d,
- DW_OP_lo_user =0xe0,
- DW_OP_hi_user =0xff,
- // GNU extensions
- DW_OP_GNU_push_tls_address =0xe0,
- // Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission.
- DW_OP_GNU_addr_index =0xfb,
- DW_OP_GNU_const_index =0xfc
-};
-
-// Section identifiers for DWP files
-enum DwarfSectionId {
- DW_SECT_INFO = 1,
- DW_SECT_TYPES = 2,
- DW_SECT_ABBREV = 3,
- DW_SECT_LINE = 4,
- DW_SECT_LOC = 5,
- DW_SECT_STR_OFFSETS = 6,
- DW_SECT_MACINFO = 7,
- DW_SECT_MACRO = 8
-};
-
-// Source languages. These are values for DW_AT_language.
-enum DwarfLanguage
- {
- DW_LANG_none =0x0000,
- DW_LANG_C89 =0x0001,
- DW_LANG_C =0x0002,
- DW_LANG_Ada83 =0x0003,
- DW_LANG_C_plus_plus =0x0004,
- DW_LANG_Cobol74 =0x0005,
- DW_LANG_Cobol85 =0x0006,
- DW_LANG_Fortran77 =0x0007,
- DW_LANG_Fortran90 =0x0008,
- DW_LANG_Pascal83 =0x0009,
- DW_LANG_Modula2 =0x000a,
- DW_LANG_Java =0x000b,
- DW_LANG_C99 =0x000c,
- DW_LANG_Ada95 =0x000d,
- DW_LANG_Fortran95 =0x000e,
- DW_LANG_PLI =0x000f,
- DW_LANG_ObjC =0x0010,
- DW_LANG_ObjC_plus_plus =0x0011,
- DW_LANG_UPC =0x0012,
- DW_LANG_D =0x0013,
- // Implementation-defined language code range.
- DW_LANG_lo_user = 0x8000,
- DW_LANG_hi_user = 0xffff,
-
- // Extensions.
-
- // MIPS assembly language. The GNU toolchain uses this for all
- // assembly languages, since there's no generic DW_LANG_ value for that.
- // See include/dwarf2.h in the binutils, gdb, or gcc source trees.
- DW_LANG_Mips_Assembler =0x8001,
- DW_LANG_Upc =0x8765 // Unified Parallel C
- };
-
-// Inline codes. These are values for DW_AT_inline.
-enum DwarfInline {
- DW_INL_not_inlined =0x0,
- DW_INL_inlined =0x1,
- DW_INL_declared_not_inlined =0x2,
- DW_INL_declared_inlined =0x3
-};
-
-// Call Frame Info instructions.
-enum DwarfCFI
- {
- DW_CFA_advance_loc = 0x40,
- DW_CFA_offset = 0x80,
- DW_CFA_restore = 0xc0,
- DW_CFA_nop = 0x00,
- DW_CFA_set_loc = 0x01,
- DW_CFA_advance_loc1 = 0x02,
- DW_CFA_advance_loc2 = 0x03,
- DW_CFA_advance_loc4 = 0x04,
- DW_CFA_offset_extended = 0x05,
- DW_CFA_restore_extended = 0x06,
- DW_CFA_undefined = 0x07,
- DW_CFA_same_value = 0x08,
- DW_CFA_register = 0x09,
- DW_CFA_remember_state = 0x0a,
- DW_CFA_restore_state = 0x0b,
- DW_CFA_def_cfa = 0x0c,
- DW_CFA_def_cfa_register = 0x0d,
- DW_CFA_def_cfa_offset = 0x0e,
- DW_CFA_def_cfa_expression = 0x0f,
- DW_CFA_expression = 0x10,
- DW_CFA_offset_extended_sf = 0x11,
- DW_CFA_def_cfa_sf = 0x12,
- DW_CFA_def_cfa_offset_sf = 0x13,
- DW_CFA_val_offset = 0x14,
- DW_CFA_val_offset_sf = 0x15,
- DW_CFA_val_expression = 0x16,
-
- // Opcodes in this range are reserved for user extensions.
- DW_CFA_lo_user = 0x1c,
- DW_CFA_hi_user = 0x3f,
-
- // SGI/MIPS specific.
- DW_CFA_MIPS_advance_loc8 = 0x1d,
-
- // GNU extensions.
- DW_CFA_GNU_window_save = 0x2d,
- DW_CFA_GNU_args_size = 0x2e,
- DW_CFA_GNU_negative_offset_extended = 0x2f
- };
-
-// Exception handling 'z' augmentation letters.
-enum DwarfZAugmentationCodes {
- // If the CFI augmentation string begins with 'z', then the CIE and FDE
- // have an augmentation data area just before the instructions, whose
- // contents are determined by the subsequent augmentation letters.
- DW_Z_augmentation_start = 'z',
-
- // If this letter is present in a 'z' augmentation string, the CIE
- // augmentation data includes a pointer encoding, and the FDE
- // augmentation data includes a language-specific data area pointer,
- // represented using that encoding.
- DW_Z_has_LSDA = 'L',
-
- // If this letter is present in a 'z' augmentation string, the CIE
- // augmentation data includes a pointer encoding, followed by a pointer
- // to a personality routine, represented using that encoding.
- DW_Z_has_personality_routine = 'P',
-
- // If this letter is present in a 'z' augmentation string, the CIE
- // augmentation data includes a pointer encoding describing how the FDE's
- // initial location, address range, and DW_CFA_set_loc operands are
- // encoded.
- DW_Z_has_FDE_address_encoding = 'R',
-
- // If this letter is present in a 'z' augmentation string, then code
- // addresses covered by FDEs that cite this CIE are signal delivery
- // trampolines. Return addresses of frames in trampolines should not be
- // adjusted as described in section 6.4.4 of the DWARF 3 spec.
- DW_Z_is_signal_trampoline = 'S'
-};
-
-// Exception handling frame description pointer formats, as described
-// by the Linux Standard Base Core Specification 4.0, section 11.5,
-// DWARF Extensions.
-enum DwarfPointerEncoding
- {
- DW_EH_PE_absptr = 0x00,
- DW_EH_PE_omit = 0xff,
- DW_EH_PE_uleb128 = 0x01,
- DW_EH_PE_udata2 = 0x02,
- DW_EH_PE_udata4 = 0x03,
- DW_EH_PE_udata8 = 0x04,
- DW_EH_PE_sleb128 = 0x09,
- DW_EH_PE_sdata2 = 0x0A,
- DW_EH_PE_sdata4 = 0x0B,
- DW_EH_PE_sdata8 = 0x0C,
- DW_EH_PE_pcrel = 0x10,
- DW_EH_PE_textrel = 0x20,
- DW_EH_PE_datarel = 0x30,
- DW_EH_PE_funcrel = 0x40,
- DW_EH_PE_aligned = 0x50,
-
- // The GNU toolchain sources define this enum value as well,
- // simply to help classify the lower nybble values into signed and
- // unsigned groups.
- DW_EH_PE_signed = 0x08,
-
- // This is not documented in LSB 4.0, but it is used in both the
- // Linux and OS X toolchains. It can be added to any other
- // encoding (except DW_EH_PE_aligned), and indicates that the
- // encoded value represents the address at which the true address
- // is stored, not the true address itself.
- DW_EH_PE_indirect = 0x80
- };
-
-} // namespace dwarf2reader
-#endif // COMMON_DWARF_DWARF2ENUMS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc
deleted file mode 100644
index a65b43c8a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.cc
+++ /dev/null
@@ -1,2734 +0,0 @@
-// 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.
-
-// CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// Implementation of dwarf2reader::LineInfo, dwarf2reader::CompilationUnit,
-// and dwarf2reader::CallFrameInfo. See dwarf2reader.h for details.
-
-#include "common/dwarf/dwarf2reader.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <memory>
-#include <stack>
-#include <string>
-#include <utility>
-
-#include <sys/stat.h>
-
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/bytereader.h"
-#include "common/dwarf/line_state_machine.h"
-#include "common/using_std_string.h"
-
-namespace dwarf2reader {
-
-CompilationUnit::CompilationUnit(const string& path,
- const SectionMap& sections, uint64 offset,
- ByteReader* reader, Dwarf2Handler* handler)
- : path_(path), offset_from_section_start_(offset), reader_(reader),
- sections_(sections), handler_(handler), abbrevs_(),
- string_buffer_(NULL), string_buffer_length_(0),
- str_offsets_buffer_(NULL), str_offsets_buffer_length_(0),
- addr_buffer_(NULL), addr_buffer_length_(0),
- is_split_dwarf_(false), dwo_id_(0), dwo_name_(),
- skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0),
- have_checked_for_dwp_(false), dwp_path_(),
- dwp_byte_reader_(), dwp_reader_() {}
-
-// Initialize a compilation unit from a .dwo or .dwp file.
-// In this case, we need the .debug_addr section from the
-// executable file that contains the corresponding skeleton
-// compilation unit. We also inherit the Dwarf2Handler from
-// the executable file, and call it as if we were still
-// processing the original compilation unit.
-
-void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer,
- uint64 addr_buffer_length,
- uint64 addr_base,
- uint64 ranges_base,
- uint64 dwo_id) {
- is_split_dwarf_ = true;
- addr_buffer_ = addr_buffer;
- addr_buffer_length_ = addr_buffer_length;
- addr_base_ = addr_base;
- ranges_base_ = ranges_base;
- skeleton_dwo_id_ = dwo_id;
-}
-
-// Read a DWARF2/3 abbreviation section.
-// Each abbrev consists of a abbreviation number, a tag, a byte
-// specifying whether the tag has children, and a list of
-// attribute/form pairs.
-// The list of forms is terminated by a 0 for the attribute, and a
-// zero for the form. The entire abbreviation section is terminated
-// by a zero for the code.
-
-void CompilationUnit::ReadAbbrevs() {
- if (abbrevs_)
- return;
-
- // First get the debug_abbrev section. ".debug_abbrev" is the name
- // recommended in the DWARF spec, and used on Linux;
- // "__debug_abbrev" is the name used in Mac OS X Mach-O files.
- SectionMap::const_iterator iter = sections_.find(".debug_abbrev");
- if (iter == sections_.end())
- iter = sections_.find("__debug_abbrev");
- assert(iter != sections_.end());
-
- abbrevs_ = new std::vector<Abbrev>;
- abbrevs_->resize(1);
-
- // The only way to check whether we are reading over the end of the
- // buffer would be to first compute the size of the leb128 data by
- // reading it, then go back and read it again.
- const uint8_t *abbrev_start = iter->second.first +
- header_.abbrev_offset;
- const uint8_t *abbrevptr = abbrev_start;
-#ifndef NDEBUG
- const uint64 abbrev_length = iter->second.second - header_.abbrev_offset;
-#endif
-
- while (1) {
- CompilationUnit::Abbrev abbrev;
- size_t len;
- const uint64 number = reader_->ReadUnsignedLEB128(abbrevptr, &len);
-
- if (number == 0)
- break;
- abbrev.number = number;
- abbrevptr += len;
-
- assert(abbrevptr < abbrev_start + abbrev_length);
- const uint64 tag = reader_->ReadUnsignedLEB128(abbrevptr, &len);
- abbrevptr += len;
- abbrev.tag = static_cast<enum DwarfTag>(tag);
-
- assert(abbrevptr < abbrev_start + abbrev_length);
- abbrev.has_children = reader_->ReadOneByte(abbrevptr);
- abbrevptr += 1;
-
- assert(abbrevptr < abbrev_start + abbrev_length);
-
- while (1) {
- const uint64 nametemp = reader_->ReadUnsignedLEB128(abbrevptr, &len);
- abbrevptr += len;
-
- assert(abbrevptr < abbrev_start + abbrev_length);
- const uint64 formtemp = reader_->ReadUnsignedLEB128(abbrevptr, &len);
- abbrevptr += len;
- if (nametemp == 0 && formtemp == 0)
- break;
-
- const enum DwarfAttribute name =
- static_cast<enum DwarfAttribute>(nametemp);
- const enum DwarfForm form = static_cast<enum DwarfForm>(formtemp);
- abbrev.attributes.push_back(std::make_pair(name, form));
- }
- assert(abbrev.number == abbrevs_->size());
- abbrevs_->push_back(abbrev);
- }
-}
-
-// Skips a single DIE's attributes.
-const uint8_t *CompilationUnit::SkipDIE(const uint8_t* start,
- const Abbrev& abbrev) {
- for (AttributeList::const_iterator i = abbrev.attributes.begin();
- i != abbrev.attributes.end();
- i++) {
- start = SkipAttribute(start, i->second);
- }
- return start;
-}
-
-// Skips a single attribute form's data.
-const uint8_t *CompilationUnit::SkipAttribute(const uint8_t *start,
- enum DwarfForm form) {
- size_t len;
-
- switch (form) {
- case DW_FORM_indirect:
- form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
- &len));
- start += len;
- return SkipAttribute(start, form);
-
- case DW_FORM_flag_present:
- return start;
- case DW_FORM_data1:
- case DW_FORM_flag:
- case DW_FORM_ref1:
- return start + 1;
- case DW_FORM_ref2:
- case DW_FORM_data2:
- return start + 2;
- case DW_FORM_ref4:
- case DW_FORM_data4:
- return start + 4;
- case DW_FORM_ref8:
- case DW_FORM_data8:
- case DW_FORM_ref_sig8:
- return start + 8;
- case DW_FORM_string:
- return start + strlen(reinterpret_cast<const char *>(start)) + 1;
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_str_index:
- case DW_FORM_GNU_addr_index:
- reader_->ReadUnsignedLEB128(start, &len);
- return start + len;
-
- case DW_FORM_sdata:
- reader_->ReadSignedLEB128(start, &len);
- return start + len;
- case DW_FORM_addr:
- return start + reader_->AddressSize();
- case DW_FORM_ref_addr:
- // DWARF2 and 3/4 differ on whether ref_addr is address size or
- // offset size.
- assert(header_.version >= 2);
- if (header_.version == 2) {
- return start + reader_->AddressSize();
- } else if (header_.version >= 3) {
- return start + reader_->OffsetSize();
- }
- break;
-
- case DW_FORM_block1:
- return start + 1 + reader_->ReadOneByte(start);
- case DW_FORM_block2:
- return start + 2 + reader_->ReadTwoBytes(start);
- case DW_FORM_block4:
- return start + 4 + reader_->ReadFourBytes(start);
- case DW_FORM_block:
- case DW_FORM_exprloc: {
- uint64 size = reader_->ReadUnsignedLEB128(start, &len);
- return start + size + len;
- }
- case DW_FORM_strp:
- case DW_FORM_sec_offset:
- return start + reader_->OffsetSize();
- }
- fprintf(stderr,"Unhandled form type");
- return NULL;
-}
-
-// Read a DWARF2/3 header.
-// The header is variable length in DWARF3 (and DWARF2 as extended by
-// most compilers), and consists of an length field, a version number,
-// the offset in the .debug_abbrev section for our abbrevs, and an
-// address size.
-void CompilationUnit::ReadHeader() {
- const uint8_t *headerptr = buffer_;
- size_t initial_length_size;
-
- assert(headerptr + 4 < buffer_ + buffer_length_);
- const uint64 initial_length
- = reader_->ReadInitialLength(headerptr, &initial_length_size);
- headerptr += initial_length_size;
- header_.length = initial_length;
-
- assert(headerptr + 2 < buffer_ + buffer_length_);
- header_.version = reader_->ReadTwoBytes(headerptr);
- headerptr += 2;
-
- assert(headerptr + reader_->OffsetSize() < buffer_ + buffer_length_);
- header_.abbrev_offset = reader_->ReadOffset(headerptr);
- headerptr += reader_->OffsetSize();
-
- // Compare against less than or equal because this may be the last
- // section in the file.
- assert(headerptr + 1 <= buffer_ + buffer_length_);
- header_.address_size = reader_->ReadOneByte(headerptr);
- reader_->SetAddressSize(header_.address_size);
- headerptr += 1;
-
- after_header_ = headerptr;
-
- // This check ensures that we don't have to do checking during the
- // reading of DIEs. header_.length does not include the size of the
- // initial length.
- assert(buffer_ + initial_length_size + header_.length <=
- buffer_ + buffer_length_);
-}
-
-uint64 CompilationUnit::Start() {
- // First get the debug_info section. ".debug_info" is the name
- // recommended in the DWARF spec, and used on Linux; "__debug_info"
- // is the name used in Mac OS X Mach-O files.
- SectionMap::const_iterator iter = sections_.find(".debug_info");
- if (iter == sections_.end())
- iter = sections_.find("__debug_info");
- assert(iter != sections_.end());
-
- // Set up our buffer
- buffer_ = iter->second.first + offset_from_section_start_;
- buffer_length_ = iter->second.second - offset_from_section_start_;
-
- // Read the header
- ReadHeader();
-
- // Figure out the real length from the end of the initial length to
- // the end of the compilation unit, since that is the value we
- // return.
- uint64 ourlength = header_.length;
- if (reader_->OffsetSize() == 8)
- ourlength += 12;
- else
- ourlength += 4;
-
- // See if the user wants this compilation unit, and if not, just return.
- if (!handler_->StartCompilationUnit(offset_from_section_start_,
- reader_->AddressSize(),
- reader_->OffsetSize(),
- header_.length,
- header_.version))
- return ourlength;
-
- // Otherwise, continue by reading our abbreviation entries.
- ReadAbbrevs();
-
- // Set the string section if we have one. ".debug_str" is the name
- // recommended in the DWARF spec, and used on Linux; "__debug_str"
- // is the name used in Mac OS X Mach-O files.
- iter = sections_.find(".debug_str");
- if (iter == sections_.end())
- iter = sections_.find("__debug_str");
- if (iter != sections_.end()) {
- string_buffer_ = iter->second.first;
- string_buffer_length_ = iter->second.second;
- }
-
- // Set the string offsets section if we have one.
- iter = sections_.find(".debug_str_offsets");
- if (iter != sections_.end()) {
- str_offsets_buffer_ = iter->second.first;
- str_offsets_buffer_length_ = iter->second.second;
- }
-
- // Set the address section if we have one.
- iter = sections_.find(".debug_addr");
- if (iter != sections_.end()) {
- addr_buffer_ = iter->second.first;
- addr_buffer_length_ = iter->second.second;
- }
-
- // Now that we have our abbreviations, start processing DIE's.
- ProcessDIEs();
-
- // If this is a skeleton compilation unit generated with split DWARF,
- // and the client needs the full debug info, we need to find the full
- // compilation unit in a .dwo or .dwp file.
- if (!is_split_dwarf_
- && dwo_name_ != NULL
- && handler_->NeedSplitDebugInfo())
- ProcessSplitDwarf();
-
- return ourlength;
-}
-
-// If one really wanted, you could merge SkipAttribute and
-// ProcessAttribute
-// This is all boring data manipulation and calling of the handler.
-const uint8_t *CompilationUnit::ProcessAttribute(
- uint64 dieoffset, const uint8_t *start, enum DwarfAttribute attr,
- enum DwarfForm form) {
- size_t len;
-
- switch (form) {
- // DW_FORM_indirect is never used because it is such a space
- // waster.
- case DW_FORM_indirect:
- form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start,
- &len));
- start += len;
- return ProcessAttribute(dieoffset, start, attr, form);
-
- case DW_FORM_flag_present:
- ProcessAttributeUnsigned(dieoffset, attr, form, 1);
- return start;
- case DW_FORM_data1:
- case DW_FORM_flag:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadOneByte(start));
- return start + 1;
- case DW_FORM_data2:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadTwoBytes(start));
- return start + 2;
- case DW_FORM_data4:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadFourBytes(start));
- return start + 4;
- case DW_FORM_data8:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadEightBytes(start));
- return start + 8;
- case DW_FORM_string: {
- const char *str = reinterpret_cast<const char *>(start);
- ProcessAttributeString(dieoffset, attr, form, str);
- return start + strlen(str) + 1;
- }
- case DW_FORM_udata:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadUnsignedLEB128(start, &len));
- return start + len;
-
- case DW_FORM_sdata:
- ProcessAttributeSigned(dieoffset, attr, form,
- reader_->ReadSignedLEB128(start, &len));
- return start + len;
- case DW_FORM_addr:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadAddress(start));
- return start + reader_->AddressSize();
- case DW_FORM_sec_offset:
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadOffset(start));
- return start + reader_->OffsetSize();
-
- case DW_FORM_ref1:
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadOneByte(start)
- + offset_from_section_start_);
- return start + 1;
- case DW_FORM_ref2:
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadTwoBytes(start)
- + offset_from_section_start_);
- return start + 2;
- case DW_FORM_ref4:
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadFourBytes(start)
- + offset_from_section_start_);
- return start + 4;
- case DW_FORM_ref8:
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadEightBytes(start)
- + offset_from_section_start_);
- return start + 8;
- case DW_FORM_ref_udata:
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadUnsignedLEB128(start,
- &len)
- + offset_from_section_start_);
- return start + len;
- case DW_FORM_ref_addr:
- // DWARF2 and 3/4 differ on whether ref_addr is address size or
- // offset size.
- assert(header_.version >= 2);
- if (header_.version == 2) {
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadAddress(start));
- return start + reader_->AddressSize();
- } else if (header_.version >= 3) {
- handler_->ProcessAttributeReference(dieoffset, attr, form,
- reader_->ReadOffset(start));
- return start + reader_->OffsetSize();
- }
- break;
- case DW_FORM_ref_sig8:
- handler_->ProcessAttributeSignature(dieoffset, attr, form,
- reader_->ReadEightBytes(start));
- return start + 8;
-
- case DW_FORM_block1: {
- uint64 datalen = reader_->ReadOneByte(start);
- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 1,
- datalen);
- return start + 1 + datalen;
- }
- case DW_FORM_block2: {
- uint64 datalen = reader_->ReadTwoBytes(start);
- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 2,
- datalen);
- return start + 2 + datalen;
- }
- case DW_FORM_block4: {
- uint64 datalen = reader_->ReadFourBytes(start);
- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + 4,
- datalen);
- return start + 4 + datalen;
- }
- case DW_FORM_block:
- case DW_FORM_exprloc: {
- uint64 datalen = reader_->ReadUnsignedLEB128(start, &len);
- handler_->ProcessAttributeBuffer(dieoffset, attr, form, start + len,
- datalen);
- return start + datalen + len;
- }
- case DW_FORM_strp: {
- assert(string_buffer_ != NULL);
-
- const uint64 offset = reader_->ReadOffset(start);
- assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_);
-
- const char *str = reinterpret_cast<const char *>(string_buffer_ + offset);
- ProcessAttributeString(dieoffset, attr, form, str);
- return start + reader_->OffsetSize();
- }
-
- case DW_FORM_GNU_str_index: {
- uint64 str_index = reader_->ReadUnsignedLEB128(start, &len);
- const uint8_t* offset_ptr =
- str_offsets_buffer_ + str_index * reader_->OffsetSize();
- const uint64 offset = reader_->ReadOffset(offset_ptr);
- if (offset >= string_buffer_length_) {
- return NULL;
- }
-
- const char* str = reinterpret_cast<const char *>(string_buffer_) + offset;
- ProcessAttributeString(dieoffset, attr, form, str);
- return start + len;
- break;
- }
- case DW_FORM_GNU_addr_index: {
- uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len);
- const uint8_t* addr_ptr =
- addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize();
- ProcessAttributeUnsigned(dieoffset, attr, form,
- reader_->ReadAddress(addr_ptr));
- return start + len;
- }
- }
- fprintf(stderr, "Unhandled form type\n");
- return NULL;
-}
-
-const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset,
- const uint8_t *start,
- const Abbrev& abbrev) {
- for (AttributeList::const_iterator i = abbrev.attributes.begin();
- i != abbrev.attributes.end();
- i++) {
- start = ProcessAttribute(dieoffset, start, i->first, i->second);
- }
-
- // If this is a compilation unit in a split DWARF object, verify that
- // the dwo_id matches. If it does not match, we will ignore this
- // compilation unit.
- if (abbrev.tag == DW_TAG_compile_unit
- && is_split_dwarf_
- && dwo_id_ != skeleton_dwo_id_) {
- return NULL;
- }
-
- return start;
-}
-
-void CompilationUnit::ProcessDIEs() {
- const uint8_t *dieptr = after_header_;
- size_t len;
-
- // lengthstart is the place the length field is based on.
- // It is the point in the header after the initial length field
- const uint8_t *lengthstart = buffer_;
-
- // In 64 bit dwarf, the initial length is 12 bytes, because of the
- // 0xffffffff at the start.
- if (reader_->OffsetSize() == 8)
- lengthstart += 12;
- else
- lengthstart += 4;
-
- std::stack<uint64> die_stack;
-
- while (dieptr < (lengthstart + header_.length)) {
- // We give the user the absolute offset from the beginning of
- // debug_info, since they need it to deal with ref_addr forms.
- uint64 absolute_offset = (dieptr - buffer_) + offset_from_section_start_;
-
- uint64 abbrev_num = reader_->ReadUnsignedLEB128(dieptr, &len);
-
- dieptr += len;
-
- // Abbrev == 0 represents the end of a list of children, or padding
- // at the end of the compilation unit.
- if (abbrev_num == 0) {
- if (die_stack.size() == 0)
- // If it is padding, then we are done with the compilation unit's DIEs.
- return;
- const uint64 offset = die_stack.top();
- die_stack.pop();
- handler_->EndDIE(offset);
- continue;
- }
-
- const Abbrev& abbrev = abbrevs_->at(static_cast<size_t>(abbrev_num));
- const enum DwarfTag tag = abbrev.tag;
- if (!handler_->StartDIE(absolute_offset, tag)) {
- dieptr = SkipDIE(dieptr, abbrev);
- } else {
- dieptr = ProcessDIE(absolute_offset, dieptr, abbrev);
- }
-
- if (abbrev.has_children) {
- die_stack.push(absolute_offset);
- } else {
- handler_->EndDIE(absolute_offset);
- }
- }
-}
-
-// Check for a valid ELF file and return the Address size.
-// Returns 0 if not a valid ELF file.
-inline int GetElfWidth(const ElfReader& elf) {
- if (elf.IsElf32File())
- return 4;
- if (elf.IsElf64File())
- return 8;
- return 0;
-}
-
-void CompilationUnit::ProcessSplitDwarf() {
- struct stat statbuf;
- if (!have_checked_for_dwp_) {
- // Look for a .dwp file in the same directory as the executable.
- have_checked_for_dwp_ = true;
- string dwp_suffix(".dwp");
- dwp_path_ = path_ + dwp_suffix;
- if (stat(dwp_path_.c_str(), &statbuf) != 0) {
- // Fall back to a split .debug file in the same directory.
- string debug_suffix(".debug");
- dwp_path_ = path_;
- size_t found = path_.rfind(debug_suffix);
- if (found + debug_suffix.length() == path_.length())
- dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix);
- }
- if (stat(dwp_path_.c_str(), &statbuf) == 0) {
- ElfReader* elf = new ElfReader(dwp_path_);
- int width = GetElfWidth(*elf);
- if (width != 0) {
- dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness()));
- dwp_byte_reader_->SetAddressSize(width);
- dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf));
- dwp_reader_->Initialize();
- } else {
- delete elf;
- }
- }
- }
- bool found_in_dwp = false;
- if (dwp_reader_) {
- // If we have a .dwp file, read the debug sections for the requested CU.
- SectionMap sections;
- dwp_reader_->ReadDebugSectionsForCU(dwo_id_, &sections);
- if (!sections.empty()) {
- found_in_dwp = true;
- CompilationUnit dwp_comp_unit(dwp_path_, sections, 0,
- dwp_byte_reader_.get(), handler_);
- dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_,
- ranges_base_, dwo_id_);
- dwp_comp_unit.Start();
- }
- }
- if (!found_in_dwp) {
- // If no .dwp file, try to open the .dwo file.
- if (stat(dwo_name_, &statbuf) == 0) {
- ElfReader elf(dwo_name_);
- int width = GetElfWidth(elf);
- if (width != 0) {
- ByteReader reader(ENDIANNESS_LITTLE);
- reader.SetAddressSize(width);
- SectionMap sections;
- ReadDebugSectionsFromDwo(&elf, &sections);
- CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader,
- handler_);
- dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_,
- addr_base_, ranges_base_, dwo_id_);
- dwo_comp_unit.Start();
- }
- }
- }
-}
-
-void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader,
- SectionMap* sections) {
- static const char* const section_names[] = {
- ".debug_abbrev",
- ".debug_info",
- ".debug_str_offsets",
- ".debug_str"
- };
- for (unsigned int i = 0u;
- i < sizeof(section_names)/sizeof(*(section_names)); ++i) {
- string base_name = section_names[i];
- string dwo_name = base_name + ".dwo";
- size_t section_size;
- const char* section_data = elf_reader->GetSectionByName(dwo_name,
- &section_size);
- if (section_data != NULL)
- sections->insert(std::make_pair(
- base_name, std::make_pair(
- reinterpret_cast<const uint8_t *>(section_data),
- section_size)));
- }
-}
-
-DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader)
- : elf_reader_(elf_reader), byte_reader_(byte_reader),
- cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL),
- string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0),
- nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL),
- offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL),
- abbrev_size_(0), info_data_(NULL), info_size_(0),
- str_offsets_data_(NULL), str_offsets_size_(0) {}
-
-DwpReader::~DwpReader() {
- if (elf_reader_) delete elf_reader_;
-}
-
-void DwpReader::Initialize() {
- cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index",
- &cu_index_size_);
- if (cu_index_ == NULL) {
- return;
- }
- // The .debug_str.dwo section is shared by all CUs in the file.
- string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo",
- &string_buffer_size_);
-
- version_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_));
-
- if (version_ == 1) {
- nslots_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_)
- + 3 * sizeof(uint32));
- phash_ = cu_index_ + 4 * sizeof(uint32);
- pindex_ = phash_ + nslots_ * sizeof(uint64);
- shndx_pool_ = pindex_ + nslots_ * sizeof(uint32);
- if (shndx_pool_ >= cu_index_ + cu_index_size_) {
- version_ = 0;
- }
- } else if (version_ == 2) {
- ncolumns_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + sizeof(uint32));
- nunits_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + 2 * sizeof(uint32));
- nslots_ = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(cu_index_) + 3 * sizeof(uint32));
- phash_ = cu_index_ + 4 * sizeof(uint32);
- pindex_ = phash_ + nslots_ * sizeof(uint64);
- offset_table_ = pindex_ + nslots_ * sizeof(uint32);
- size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32);
- abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo",
- &abbrev_size_);
- info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_);
- str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo",
- &str_offsets_size_);
- if (size_table_ >= cu_index_ + cu_index_size_) {
- version_ = 0;
- }
- }
-}
-
-void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id,
- SectionMap* sections) {
- if (version_ == 1) {
- int slot = LookupCU(dwo_id);
- if (slot == -1) {
- return;
- }
-
- // The index table points to the section index pool, where we
- // can read a list of section indexes for the debug sections
- // for the CU whose dwo_id we are looking for.
- int index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_)
- + slot * sizeof(uint32));
- const char* shndx_list = shndx_pool_ + index * sizeof(uint32);
- for (;;) {
- if (shndx_list >= cu_index_ + cu_index_size_) {
- version_ = 0;
- return;
- }
- unsigned int shndx = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(shndx_list));
- shndx_list += sizeof(uint32);
- if (shndx == 0)
- break;
- const char* section_name = elf_reader_->GetSectionName(shndx);
- size_t section_size;
- const char* section_data;
- // We're only interested in these four debug sections.
- // The section names in the .dwo file end with ".dwo", but we
- // add them to the sections table with their normal names.
- if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) {
- section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
- sections->insert(std::make_pair(
- ".debug_abbrev",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
- section_size)));
- } else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) {
- section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
- sections->insert(std::make_pair(
- ".debug_info",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
- section_size)));
- } else if (!strncmp(section_name, ".debug_str_offsets",
- strlen(".debug_str_offsets"))) {
- section_data = elf_reader_->GetSectionByIndex(shndx, &section_size);
- sections->insert(std::make_pair(
- ".debug_str_offsets",
- std::make_pair(reinterpret_cast<const uint8_t *> (section_data),
- section_size)));
- }
- }
- sections->insert(std::make_pair(
- ".debug_str",
- std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
- string_buffer_size_)));
- } else if (version_ == 2) {
- uint32 index = LookupCUv2(dwo_id);
- if (index == 0) {
- return;
- }
-
- // The index points to a row in each of the section offsets table
- // and the section size table, where we can read the offsets and sizes
- // of the contributions to each debug section from the CU whose dwo_id
- // we are looking for. Row 0 of the section offsets table has the
- // section ids for each column of the table. The size table begins
- // with row 1.
- const char* id_row = offset_table_;
- const char* offset_row = offset_table_
- + index * ncolumns_ * sizeof(uint32);
- const char* size_row =
- size_table_ + (index - 1) * ncolumns_ * sizeof(uint32);
- if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) {
- version_ = 0;
- return;
- }
- for (unsigned int col = 0u; col < ncolumns_; ++col) {
- uint32 section_id =
- byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row)
- + col * sizeof(uint32));
- uint32 offset = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(offset_row)
- + col * sizeof(uint32));
- uint32 size = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(size_row) + col * sizeof(uint32));
- if (section_id == DW_SECT_ABBREV) {
- sections->insert(std::make_pair(
- ".debug_abbrev",
- std::make_pair(reinterpret_cast<const uint8_t *> (abbrev_data_)
- + offset, size)));
- } else if (section_id == DW_SECT_INFO) {
- sections->insert(std::make_pair(
- ".debug_info",
- std::make_pair(reinterpret_cast<const uint8_t *> (info_data_)
- + offset, size)));
- } else if (section_id == DW_SECT_STR_OFFSETS) {
- sections->insert(std::make_pair(
- ".debug_str_offsets",
- std::make_pair(reinterpret_cast<const uint8_t *> (str_offsets_data_)
- + offset, size)));
- }
- }
- sections->insert(std::make_pair(
- ".debug_str",
- std::make_pair(reinterpret_cast<const uint8_t *> (string_buffer_),
- string_buffer_size_)));
- }
-}
-
-int DwpReader::LookupCU(uint64 dwo_id) {
- uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
- uint64 probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
- if (probe != 0 && probe != dwo_id) {
- uint32 secondary_hash =
- (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
- do {
- slot = (slot + secondary_hash) & (nslots_ - 1);
- probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
- } while (probe != 0 && probe != dwo_id);
- }
- if (probe == 0)
- return -1;
- return slot;
-}
-
-uint32 DwpReader::LookupCUv2(uint64 dwo_id) {
- uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1);
- uint64 probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
- uint32 index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
- if (index != 0 && probe != dwo_id) {
- uint32 secondary_hash =
- (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1;
- do {
- slot = (slot + secondary_hash) & (nslots_ - 1);
- probe = byte_reader_.ReadEightBytes(
- reinterpret_cast<const uint8_t *>(phash_) + slot * sizeof(uint64));
- index = byte_reader_.ReadFourBytes(
- reinterpret_cast<const uint8_t *>(pindex_) + slot * sizeof(uint32));
- } while (index != 0 && probe != dwo_id);
- }
- return index;
-}
-
-LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length,
- ByteReader* reader, LineInfoHandler* handler):
- handler_(handler), reader_(reader), buffer_(buffer) {
-#ifndef NDEBUG
- buffer_length_ = buffer_length;
-#endif
- header_.std_opcode_lengths = NULL;
-}
-
-uint64 LineInfo::Start() {
- ReadHeader();
- ReadLines();
- return after_header_ - buffer_;
-}
-
-// The header for a debug_line section is mildly complicated, because
-// the line info is very tightly encoded.
-void LineInfo::ReadHeader() {
- const uint8_t *lineptr = buffer_;
- size_t initial_length_size;
-
- const uint64 initial_length
- = reader_->ReadInitialLength(lineptr, &initial_length_size);
-
- lineptr += initial_length_size;
- header_.total_length = initial_length;
- assert(buffer_ + initial_length_size + header_.total_length <=
- buffer_ + buffer_length_);
-
- // Address size *must* be set by CU ahead of time.
- assert(reader_->AddressSize() != 0);
-
- header_.version = reader_->ReadTwoBytes(lineptr);
- lineptr += 2;
-
- header_.prologue_length = reader_->ReadOffset(lineptr);
- lineptr += reader_->OffsetSize();
-
- header_.min_insn_length = reader_->ReadOneByte(lineptr);
- lineptr += 1;
-
- header_.default_is_stmt = reader_->ReadOneByte(lineptr);
- lineptr += 1;
-
- header_.line_base = *reinterpret_cast<const int8*>(lineptr);
- lineptr += 1;
-
- header_.line_range = reader_->ReadOneByte(lineptr);
- lineptr += 1;
-
- header_.opcode_base = reader_->ReadOneByte(lineptr);
- lineptr += 1;
-
- header_.std_opcode_lengths = new std::vector<unsigned char>;
- header_.std_opcode_lengths->resize(header_.opcode_base + 1);
- (*header_.std_opcode_lengths)[0] = 0;
- for (int i = 1; i < header_.opcode_base; i++) {
- (*header_.std_opcode_lengths)[i] = reader_->ReadOneByte(lineptr);
- lineptr += 1;
- }
-
- // It is legal for the directory entry table to be empty.
- if (*lineptr) {
- uint32 dirindex = 1;
- while (*lineptr) {
- const char *dirname = reinterpret_cast<const char *>(lineptr);
- handler_->DefineDir(dirname, dirindex);
- lineptr += strlen(dirname) + 1;
- dirindex++;
- }
- }
- lineptr++;
-
- // It is also legal for the file entry table to be empty.
- if (*lineptr) {
- uint32 fileindex = 1;
- size_t len;
- while (*lineptr) {
- const char *filename = reinterpret_cast<const char *>(lineptr);
- lineptr += strlen(filename) + 1;
-
- uint64 dirindex = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
-
- uint64 mod_time = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
-
- uint64 filelength = reader_->ReadUnsignedLEB128(lineptr, &len);
- lineptr += len;
- handler_->DefineFile(filename, fileindex, static_cast<uint32>(dirindex),
- mod_time, filelength);
- fileindex++;
- }
- }
- lineptr++;
-
- after_header_ = lineptr;
-}
-
-/* static */
-bool LineInfo::ProcessOneOpcode(ByteReader* reader,
- LineInfoHandler* handler,
- const struct LineInfoHeader &header,
- const uint8_t *start,
- struct LineStateMachine* lsm,
- size_t* len,
- uintptr pc,
- bool *lsm_passes_pc) {
- size_t oplen = 0;
- size_t templen;
- uint8 opcode = reader->ReadOneByte(start);
- oplen++;
- start++;
-
- // If the opcode is great than the opcode_base, it is a special
- // opcode. Most line programs consist mainly of special opcodes.
- if (opcode >= header.opcode_base) {
- opcode -= header.opcode_base;
- const int64 advance_address = (opcode / header.line_range)
- * header.min_insn_length;
- const int32 advance_line = (opcode % header.line_range)
- + header.line_base;
-
- // Check if the lsm passes "pc". If so, mark it as passed.
- if (lsm_passes_pc &&
- lsm->address <= pc && pc < lsm->address + advance_address) {
- *lsm_passes_pc = true;
- }
-
- lsm->address += advance_address;
- lsm->line_num += advance_line;
- lsm->basic_block = true;
- *len = oplen;
- return true;
- }
-
- // Otherwise, we have the regular opcodes
- switch (opcode) {
- case DW_LNS_copy: {
- lsm->basic_block = false;
- *len = oplen;
- return true;
- }
-
- case DW_LNS_advance_pc: {
- uint64 advance_address = reader->ReadUnsignedLEB128(start, &templen);
- oplen += templen;
-
- // Check if the lsm passes "pc". If so, mark it as passed.
- if (lsm_passes_pc && lsm->address <= pc &&
- pc < lsm->address + header.min_insn_length * advance_address) {
- *lsm_passes_pc = true;
- }
-
- lsm->address += header.min_insn_length * advance_address;
- }
- break;
- case DW_LNS_advance_line: {
- const int64 advance_line = reader->ReadSignedLEB128(start, &templen);
- oplen += templen;
- lsm->line_num += static_cast<int32>(advance_line);
-
- // With gcc 4.2.1, we can get the line_no here for the first time
- // since DW_LNS_advance_line is called after DW_LNE_set_address is
- // called. So we check if the lsm passes "pc" here, not in
- // DW_LNE_set_address.
- if (lsm_passes_pc && lsm->address == pc) {
- *lsm_passes_pc = true;
- }
- }
- break;
- case DW_LNS_set_file: {
- const uint64 fileno = reader->ReadUnsignedLEB128(start, &templen);
- oplen += templen;
- lsm->file_num = static_cast<uint32>(fileno);
- }
- break;
- case DW_LNS_set_column: {
- const uint64 colno = reader->ReadUnsignedLEB128(start, &templen);
- oplen += templen;
- lsm->column_num = static_cast<uint32>(colno);
- }
- break;
- case DW_LNS_negate_stmt: {
- lsm->is_stmt = !lsm->is_stmt;
- }
- break;
- case DW_LNS_set_basic_block: {
- lsm->basic_block = true;
- }
- break;
- case DW_LNS_fixed_advance_pc: {
- const uint16 advance_address = reader->ReadTwoBytes(start);
- oplen += 2;
-
- // Check if the lsm passes "pc". If so, mark it as passed.
- if (lsm_passes_pc &&
- lsm->address <= pc && pc < lsm->address + advance_address) {
- *lsm_passes_pc = true;
- }
-
- lsm->address += advance_address;
- }
- break;
- case DW_LNS_const_add_pc: {
- const int64 advance_address = header.min_insn_length
- * ((255 - header.opcode_base)
- / header.line_range);
-
- // Check if the lsm passes "pc". If so, mark it as passed.
- if (lsm_passes_pc &&
- lsm->address <= pc && pc < lsm->address + advance_address) {
- *lsm_passes_pc = true;
- }
-
- lsm->address += advance_address;
- }
- break;
- case DW_LNS_extended_op: {
- const uint64 extended_op_len = reader->ReadUnsignedLEB128(start,
- &templen);
- start += templen;
- oplen += templen + extended_op_len;
-
- const uint64 extended_op = reader->ReadOneByte(start);
- start++;
-
- switch (extended_op) {
- case DW_LNE_end_sequence: {
- lsm->end_sequence = true;
- *len = oplen;
- return true;
- }
- break;
- case DW_LNE_set_address: {
- // With gcc 4.2.1, we cannot tell the line_no here since
- // DW_LNE_set_address is called before DW_LNS_advance_line is
- // called. So we do not check if the lsm passes "pc" here. See
- // also the comment in DW_LNS_advance_line.
- uint64 address = reader->ReadAddress(start);
- lsm->address = address;
- }
- break;
- case DW_LNE_define_file: {
- const char *filename = reinterpret_cast<const char *>(start);
-
- templen = strlen(filename) + 1;
- start += templen;
-
- uint64 dirindex = reader->ReadUnsignedLEB128(start, &templen);
- oplen += templen;
-
- const uint64 mod_time = reader->ReadUnsignedLEB128(start,
- &templen);
- oplen += templen;
-
- const uint64 filelength = reader->ReadUnsignedLEB128(start,
- &templen);
- oplen += templen;
-
- if (handler) {
- handler->DefineFile(filename, -1, static_cast<uint32>(dirindex),
- mod_time, filelength);
- }
- }
- break;
- }
- }
- break;
-
- default: {
- // Ignore unknown opcode silently
- if (header.std_opcode_lengths) {
- for (int i = 0; i < (*header.std_opcode_lengths)[opcode]; i++) {
- reader->ReadUnsignedLEB128(start, &templen);
- start += templen;
- oplen += templen;
- }
- }
- }
- break;
- }
- *len = oplen;
- return false;
-}
-
-void LineInfo::ReadLines() {
- struct LineStateMachine lsm;
-
- // lengthstart is the place the length field is based on.
- // It is the point in the header after the initial length field
- const uint8_t *lengthstart = buffer_;
-
- // In 64 bit dwarf, the initial length is 12 bytes, because of the
- // 0xffffffff at the start.
- if (reader_->OffsetSize() == 8)
- lengthstart += 12;
- else
- lengthstart += 4;
-
- const uint8_t *lineptr = after_header_;
- lsm.Reset(header_.default_is_stmt);
-
- // The LineInfoHandler interface expects each line's length along
- // with its address, but DWARF only provides addresses (sans
- // length), and an end-of-sequence address; one infers the length
- // from the next address. So we report a line only when we get the
- // next line's address, or the end-of-sequence address.
- bool have_pending_line = false;
- uint64 pending_address = 0;
- uint32 pending_file_num = 0, pending_line_num = 0, pending_column_num = 0;
-
- while (lineptr < lengthstart + header_.total_length) {
- size_t oplength;
- bool add_row = ProcessOneOpcode(reader_, handler_, header_,
- lineptr, &lsm, &oplength, (uintptr)-1,
- NULL);
- if (add_row) {
- if (have_pending_line)
- handler_->AddLine(pending_address, lsm.address - pending_address,
- pending_file_num, pending_line_num,
- pending_column_num);
- if (lsm.end_sequence) {
- lsm.Reset(header_.default_is_stmt);
- have_pending_line = false;
- } else {
- pending_address = lsm.address;
- pending_file_num = lsm.file_num;
- pending_line_num = lsm.line_num;
- pending_column_num = lsm.column_num;
- have_pending_line = true;
- }
- }
- lineptr += oplength;
- }
-
- after_header_ = lengthstart + header_.total_length;
-}
-
-// A DWARF rule for recovering the address or value of a register, or
-// computing the canonical frame address. There is one subclass of this for
-// each '*Rule' member function in CallFrameInfo::Handler.
-//
-// It's annoying that we have to handle Rules using pointers (because
-// the concrete instances can have an arbitrary size). They're small,
-// so it would be much nicer if we could just handle them by value
-// instead of fretting about ownership and destruction.
-//
-// It seems like all these could simply be instances of std::tr1::bind,
-// except that we need instances to be EqualityComparable, too.
-//
-// This could logically be nested within State, but then the qualified names
-// get horrendous.
-class CallFrameInfo::Rule {
- public:
- virtual ~Rule() { }
-
- // Tell HANDLER that, at ADDRESS in the program, REGISTER can be
- // recovered using this rule. If REGISTER is kCFARegister, then this rule
- // describes how to compute the canonical frame address. Return what the
- // HANDLER member function returned.
- virtual bool Handle(Handler *handler,
- uint64 address, int register) const = 0;
-
- // Equality on rules. We use these to decide which rules we need
- // to report after a DW_CFA_restore_state instruction.
- virtual bool operator==(const Rule &rhs) const = 0;
-
- bool operator!=(const Rule &rhs) const { return ! (*this == rhs); }
-
- // Return a pointer to a copy of this rule.
- virtual Rule *Copy() const = 0;
-
- // If this is a base+offset rule, change its base register to REG.
- // Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.)
- virtual void SetBaseRegister(unsigned reg) { }
-
- // If this is a base+offset rule, change its offset to OFFSET. Otherwise,
- // do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.)
- virtual void SetOffset(long long offset) { }
-};
-
-// Rule: the value the register had in the caller cannot be recovered.
-class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule {
- public:
- UndefinedRule() { }
- ~UndefinedRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->UndefinedRule(address, reg);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const UndefinedRule *our_rhs = dynamic_cast<const UndefinedRule *>(&rhs);
- return (our_rhs != NULL);
- }
- Rule *Copy() const { return new UndefinedRule(*this); }
-};
-
-// Rule: the register's value is the same as that it had in the caller.
-class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule {
- public:
- SameValueRule() { }
- ~SameValueRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->SameValueRule(address, reg);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const SameValueRule *our_rhs = dynamic_cast<const SameValueRule *>(&rhs);
- return (our_rhs != NULL);
- }
- Rule *Copy() const { return new SameValueRule(*this); }
-};
-
-// Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER
-// may be CallFrameInfo::Handler::kCFARegister.
-class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule {
- public:
- OffsetRule(int base_register, long offset)
- : base_register_(base_register), offset_(offset) { }
- ~OffsetRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->OffsetRule(address, reg, base_register_, offset_);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const OffsetRule *our_rhs = dynamic_cast<const OffsetRule *>(&rhs);
- return (our_rhs &&
- base_register_ == our_rhs->base_register_ &&
- offset_ == our_rhs->offset_);
- }
- Rule *Copy() const { return new OffsetRule(*this); }
- // We don't actually need SetBaseRegister or SetOffset here, since they
- // are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it
- // doesn't make sense to use OffsetRule for computing the CFA: it
- // computes the address at which a register is saved, not a value.
- private:
- int base_register_;
- long offset_;
-};
-
-// Rule: the value the register had in the caller is the value of
-// BASE_REGISTER plus offset. BASE_REGISTER may be
-// CallFrameInfo::Handler::kCFARegister.
-class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule {
- public:
- ValOffsetRule(int base_register, long offset)
- : base_register_(base_register), offset_(offset) { }
- ~ValOffsetRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->ValOffsetRule(address, reg, base_register_, offset_);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ValOffsetRule *our_rhs = dynamic_cast<const ValOffsetRule *>(&rhs);
- return (our_rhs &&
- base_register_ == our_rhs->base_register_ &&
- offset_ == our_rhs->offset_);
- }
- Rule *Copy() const { return new ValOffsetRule(*this); }
- void SetBaseRegister(unsigned reg) { base_register_ = reg; }
- void SetOffset(long long offset) { offset_ = offset; }
- private:
- int base_register_;
- long offset_;
-};
-
-// Rule: the register has been saved in another register REGISTER_NUMBER_.
-class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule {
- public:
- explicit RegisterRule(int register_number)
- : register_number_(register_number) { }
- ~RegisterRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->RegisterRule(address, reg, register_number_);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const RegisterRule *our_rhs = dynamic_cast<const RegisterRule *>(&rhs);
- return (our_rhs && register_number_ == our_rhs->register_number_);
- }
- Rule *Copy() const { return new RegisterRule(*this); }
- private:
- int register_number_;
-};
-
-// Rule: EXPRESSION evaluates to the address at which the register is saved.
-class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule {
- public:
- explicit ExpressionRule(const string &expression)
- : expression_(expression) { }
- ~ExpressionRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->ExpressionRule(address, reg, expression_);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ExpressionRule *our_rhs = dynamic_cast<const ExpressionRule *>(&rhs);
- return (our_rhs && expression_ == our_rhs->expression_);
- }
- Rule *Copy() const { return new ExpressionRule(*this); }
- private:
- string expression_;
-};
-
-// Rule: EXPRESSION evaluates to the address at which the register is saved.
-class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule {
- public:
- explicit ValExpressionRule(const string &expression)
- : expression_(expression) { }
- ~ValExpressionRule() { }
- bool Handle(Handler *handler, uint64 address, int reg) const {
- return handler->ValExpressionRule(address, reg, expression_);
- }
- bool operator==(const Rule &rhs) const {
- // dynamic_cast is allowed by the Google C++ Style Guide, if the use has
- // been carefully considered; cheap RTTI-like workarounds are forbidden.
- const ValExpressionRule *our_rhs =
- dynamic_cast<const ValExpressionRule *>(&rhs);
- return (our_rhs && expression_ == our_rhs->expression_);
- }
- Rule *Copy() const { return new ValExpressionRule(*this); }
- private:
- string expression_;
-};
-
-// A map from register numbers to rules.
-class CallFrameInfo::RuleMap {
- public:
- RuleMap() : cfa_rule_(NULL) { }
- RuleMap(const RuleMap &rhs) : cfa_rule_(NULL) { *this = rhs; }
- ~RuleMap() { Clear(); }
-
- RuleMap &operator=(const RuleMap &rhs);
-
- // Set the rule for computing the CFA to RULE. Take ownership of RULE.
- void SetCFARule(Rule *rule) { delete cfa_rule_; cfa_rule_ = rule; }
-
- // Return the current CFA rule. Unlike RegisterRule, this RuleMap retains
- // ownership of the rule. We use this for DW_CFA_def_cfa_offset and
- // DW_CFA_def_cfa_register, and for detecting references to the CFA before
- // a rule for it has been established.
- Rule *CFARule() const { return cfa_rule_; }
-
- // Return the rule for REG, or NULL if there is none. The caller takes
- // ownership of the result.
- Rule *RegisterRule(int reg) const;
-
- // Set the rule for computing REG to RULE. Take ownership of RULE.
- void SetRegisterRule(int reg, Rule *rule);
-
- // Make all the appropriate calls to HANDLER as if we were changing from
- // this RuleMap to NEW_RULES at ADDRESS. We use this to implement
- // DW_CFA_restore_state, where lots of rules can change simultaneously.
- // Return true if all handlers returned true; otherwise, return false.
- bool HandleTransitionTo(Handler *handler, uint64 address,
- const RuleMap &new_rules) const;
-
- private:
- // A map from register numbers to Rules.
- typedef std::map<int, Rule *> RuleByNumber;
-
- // Remove all register rules and clear cfa_rule_.
- void Clear();
-
- // The rule for computing the canonical frame address. This RuleMap owns
- // this rule.
- Rule *cfa_rule_;
-
- // A map from register numbers to postfix expressions to recover
- // their values. This RuleMap owns the Rules the map refers to.
- RuleByNumber registers_;
-};
-
-CallFrameInfo::RuleMap &CallFrameInfo::RuleMap::operator=(const RuleMap &rhs) {
- Clear();
- // Since each map owns the rules it refers to, assignment must copy them.
- if (rhs.cfa_rule_) cfa_rule_ = rhs.cfa_rule_->Copy();
- for (RuleByNumber::const_iterator it = rhs.registers_.begin();
- it != rhs.registers_.end(); it++)
- registers_[it->first] = it->second->Copy();
- return *this;
-}
-
-CallFrameInfo::Rule *CallFrameInfo::RuleMap::RegisterRule(int reg) const {
- assert(reg != Handler::kCFARegister);
- RuleByNumber::const_iterator it = registers_.find(reg);
- if (it != registers_.end())
- return it->second->Copy();
- else
- return NULL;
-}
-
-void CallFrameInfo::RuleMap::SetRegisterRule(int reg, Rule *rule) {
- assert(reg != Handler::kCFARegister);
- assert(rule);
- Rule **slot = &registers_[reg];
- delete *slot;
- *slot = rule;
-}
-
-bool CallFrameInfo::RuleMap::HandleTransitionTo(
- Handler *handler,
- uint64 address,
- const RuleMap &new_rules) const {
- // Transition from cfa_rule_ to new_rules.cfa_rule_.
- if (cfa_rule_ && new_rules.cfa_rule_) {
- if (*cfa_rule_ != *new_rules.cfa_rule_ &&
- !new_rules.cfa_rule_->Handle(handler, address,
- Handler::kCFARegister))
- return false;
- } else if (cfa_rule_) {
- // this RuleMap has a CFA rule but new_rules doesn't.
- // CallFrameInfo::Handler has no way to handle this --- and shouldn't;
- // it's garbage input. The instruction interpreter should have
- // detected this and warned, so take no action here.
- } else if (new_rules.cfa_rule_) {
- // This shouldn't be possible: NEW_RULES is some prior state, and
- // there's no way to remove entries.
- assert(0);
- } else {
- // Both CFA rules are empty. No action needed.
- }
-
- // Traverse the two maps in order by register number, and report
- // whatever differences we find.
- RuleByNumber::const_iterator old_it = registers_.begin();
- RuleByNumber::const_iterator new_it = new_rules.registers_.begin();
- while (old_it != registers_.end() && new_it != new_rules.registers_.end()) {
- if (old_it->first < new_it->first) {
- // This RuleMap has an entry for old_it->first, but NEW_RULES
- // doesn't.
- //
- // This isn't really the right thing to do, but since CFI generally
- // only mentions callee-saves registers, and GCC's convention for
- // callee-saves registers is that they are unchanged, it's a good
- // approximation.
- if (!handler->SameValueRule(address, old_it->first))
- return false;
- old_it++;
- } else if (old_it->first > new_it->first) {
- // NEW_RULES has entry for new_it->first, but this RuleMap
- // doesn't. This shouldn't be possible: NEW_RULES is some prior
- // state, and there's no way to remove entries.
- assert(0);
- } else {
- // Both maps have an entry for this register. Report the new
- // rule if it is different.
- if (*old_it->second != *new_it->second &&
- !new_it->second->Handle(handler, address, new_it->first))
- return false;
- new_it++, old_it++;
- }
- }
- // Finish off entries from this RuleMap with no counterparts in new_rules.
- while (old_it != registers_.end()) {
- if (!handler->SameValueRule(address, old_it->first))
- return false;
- old_it++;
- }
- // Since we only make transitions from a rule set to some previously
- // saved rule set, and we can only add rules to the map, NEW_RULES
- // must have fewer rules than *this.
- assert(new_it == new_rules.registers_.end());
-
- return true;
-}
-
-// Remove all register rules and clear cfa_rule_.
-void CallFrameInfo::RuleMap::Clear() {
- delete cfa_rule_;
- cfa_rule_ = NULL;
- for (RuleByNumber::iterator it = registers_.begin();
- it != registers_.end(); it++)
- delete it->second;
- registers_.clear();
-}
-
-// The state of the call frame information interpreter as it processes
-// instructions from a CIE and FDE.
-class CallFrameInfo::State {
- public:
- // Create a call frame information interpreter state with the given
- // reporter, reader, handler, and initial call frame info address.
- State(ByteReader *reader, Handler *handler, Reporter *reporter,
- uint64 address)
- : reader_(reader), handler_(handler), reporter_(reporter),
- address_(address), entry_(NULL), cursor_(NULL) { }
-
- // Interpret instructions from CIE, save the resulting rule set for
- // DW_CFA_restore instructions, and return true. On error, report
- // the problem to reporter_ and return false.
- bool InterpretCIE(const CIE &cie);
-
- // Interpret instructions from FDE, and return true. On error,
- // report the problem to reporter_ and return false.
- bool InterpretFDE(const FDE &fde);
-
- private:
- // The operands of a CFI instruction, for ParseOperands.
- struct Operands {
- unsigned register_number; // A register number.
- uint64 offset; // An offset or address.
- long signed_offset; // A signed offset.
- string expression; // A DWARF expression.
- };
-
- // Parse CFI instruction operands from STATE's instruction stream as
- // described by FORMAT. On success, populate OPERANDS with the
- // results, and return true. On failure, report the problem and
- // return false.
- //
- // Each character of FORMAT should be one of the following:
- //
- // 'r' unsigned LEB128 register number (OPERANDS->register_number)
- // 'o' unsigned LEB128 offset (OPERANDS->offset)
- // 's' signed LEB128 offset (OPERANDS->signed_offset)
- // 'a' machine-size address (OPERANDS->offset)
- // (If the CIE has a 'z' augmentation string, 'a' uses the
- // encoding specified by the 'R' argument.)
- // '1' a one-byte offset (OPERANDS->offset)
- // '2' a two-byte offset (OPERANDS->offset)
- // '4' a four-byte offset (OPERANDS->offset)
- // '8' an eight-byte offset (OPERANDS->offset)
- // 'e' a DW_FORM_block holding a (OPERANDS->expression)
- // DWARF expression
- bool ParseOperands(const char *format, Operands *operands);
-
- // Interpret one CFI instruction from STATE's instruction stream, update
- // STATE, report any rule changes to handler_, and return true. On
- // failure, report the problem and return false.
- bool DoInstruction();
-
- // The following Do* member functions are subroutines of DoInstruction,
- // factoring out the actual work of operations that have several
- // different encodings.
-
- // Set the CFA rule to be the value of BASE_REGISTER plus OFFSET, and
- // return true. On failure, report and return false. (Used for
- // DW_CFA_def_cfa and DW_CFA_def_cfa_sf.)
- bool DoDefCFA(unsigned base_register, long offset);
-
- // Change the offset of the CFA rule to OFFSET, and return true. On
- // failure, report and return false. (Subroutine for
- // DW_CFA_def_cfa_offset and DW_CFA_def_cfa_offset_sf.)
- bool DoDefCFAOffset(long offset);
-
- // Specify that REG can be recovered using RULE, and return true. On
- // failure, report and return false.
- bool DoRule(unsigned reg, Rule *rule);
-
- // Specify that REG can be found at OFFSET from the CFA, and return true.
- // On failure, report and return false. (Subroutine for DW_CFA_offset,
- // DW_CFA_offset_extended, and DW_CFA_offset_extended_sf.)
- bool DoOffset(unsigned reg, long offset);
-
- // Specify that the caller's value for REG is the CFA plus OFFSET,
- // and return true. On failure, report and return false. (Subroutine
- // for DW_CFA_val_offset and DW_CFA_val_offset_sf.)
- bool DoValOffset(unsigned reg, long offset);
-
- // Restore REG to the rule established in the CIE, and return true. On
- // failure, report and return false. (Subroutine for DW_CFA_restore and
- // DW_CFA_restore_extended.)
- bool DoRestore(unsigned reg);
-
- // Return the section offset of the instruction at cursor. For use
- // in error messages.
- uint64 CursorOffset() { return entry_->offset + (cursor_ - entry_->start); }
-
- // Report that entry_ is incomplete, and return false. For brevity.
- bool ReportIncomplete() {
- reporter_->Incomplete(entry_->offset, entry_->kind);
- return false;
- }
-
- // For reading multi-byte values with the appropriate endianness.
- ByteReader *reader_;
-
- // The handler to which we should report the data we find.
- Handler *handler_;
-
- // For reporting problems in the info we're parsing.
- Reporter *reporter_;
-
- // The code address to which the next instruction in the stream applies.
- uint64 address_;
-
- // The entry whose instructions we are currently processing. This is
- // first a CIE, and then an FDE.
- const Entry *entry_;
-
- // The next instruction to process.
- const uint8_t *cursor_;
-
- // The current set of rules.
- RuleMap rules_;
-
- // The set of rules established by the CIE, used by DW_CFA_restore
- // and DW_CFA_restore_extended. We set this after interpreting the
- // CIE's instructions.
- RuleMap cie_rules_;
-
- // A stack of saved states, for DW_CFA_remember_state and
- // DW_CFA_restore_state.
- std::stack<RuleMap> saved_rules_;
-};
-
-bool CallFrameInfo::State::InterpretCIE(const CIE &cie) {
- entry_ = &cie;
- cursor_ = entry_->instructions;
- while (cursor_ < entry_->end)
- if (!DoInstruction())
- return false;
- // Note the rules established by the CIE, for use by DW_CFA_restore
- // and DW_CFA_restore_extended.
- cie_rules_ = rules_;
- return true;
-}
-
-bool CallFrameInfo::State::InterpretFDE(const FDE &fde) {
- entry_ = &fde;
- cursor_ = entry_->instructions;
- while (cursor_ < entry_->end)
- if (!DoInstruction())
- return false;
- return true;
-}
-
-bool CallFrameInfo::State::ParseOperands(const char *format,
- Operands *operands) {
- size_t len;
- const char *operand;
-
- for (operand = format; *operand; operand++) {
- size_t bytes_left = entry_->end - cursor_;
- switch (*operand) {
- case 'r':
- operands->register_number = reader_->ReadUnsignedLEB128(cursor_, &len);
- if (len > bytes_left) return ReportIncomplete();
- cursor_ += len;
- break;
-
- case 'o':
- operands->offset = reader_->ReadUnsignedLEB128(cursor_, &len);
- if (len > bytes_left) return ReportIncomplete();
- cursor_ += len;
- break;
-
- case 's':
- operands->signed_offset = reader_->ReadSignedLEB128(cursor_, &len);
- if (len > bytes_left) return ReportIncomplete();
- cursor_ += len;
- break;
-
- case 'a':
- operands->offset =
- reader_->ReadEncodedPointer(cursor_, entry_->cie->pointer_encoding,
- &len);
- if (len > bytes_left) return ReportIncomplete();
- cursor_ += len;
- break;
-
- case '1':
- if (1 > bytes_left) return ReportIncomplete();
- operands->offset = static_cast<unsigned char>(*cursor_++);
- break;
-
- case '2':
- if (2 > bytes_left) return ReportIncomplete();
- operands->offset = reader_->ReadTwoBytes(cursor_);
- cursor_ += 2;
- break;
-
- case '4':
- if (4 > bytes_left) return ReportIncomplete();
- operands->offset = reader_->ReadFourBytes(cursor_);
- cursor_ += 4;
- break;
-
- case '8':
- if (8 > bytes_left) return ReportIncomplete();
- operands->offset = reader_->ReadEightBytes(cursor_);
- cursor_ += 8;
- break;
-
- case 'e': {
- size_t expression_length = reader_->ReadUnsignedLEB128(cursor_, &len);
- if (len > bytes_left || expression_length > bytes_left - len)
- return ReportIncomplete();
- cursor_ += len;
- operands->expression = string(reinterpret_cast<const char *>(cursor_),
- expression_length);
- cursor_ += expression_length;
- break;
- }
-
- default:
- assert(0);
- }
- }
-
- return true;
-}
-
-bool CallFrameInfo::State::DoInstruction() {
- CIE *cie = entry_->cie;
- Operands ops;
-
- // Our entry's kind should have been set by now.
- assert(entry_->kind != kUnknown);
-
- // We shouldn't have been invoked unless there were more
- // instructions to parse.
- assert(cursor_ < entry_->end);
-
- unsigned opcode = *cursor_++;
- if ((opcode & 0xc0) != 0) {
- switch (opcode & 0xc0) {
- // Advance the address.
- case DW_CFA_advance_loc: {
- size_t code_offset = opcode & 0x3f;
- address_ += code_offset * cie->code_alignment_factor;
- break;
- }
-
- // Find a register at an offset from the CFA.
- case DW_CFA_offset:
- if (!ParseOperands("o", &ops) ||
- !DoOffset(opcode & 0x3f, ops.offset * cie->data_alignment_factor))
- return false;
- break;
-
- // Restore the rule established for a register by the CIE.
- case DW_CFA_restore:
- if (!DoRestore(opcode & 0x3f)) return false;
- break;
-
- // The 'if' above should have excluded this possibility.
- default:
- assert(0);
- }
-
- // Return here, so the big switch below won't be indented.
- return true;
- }
-
- switch (opcode) {
- // Set the address.
- case DW_CFA_set_loc:
- if (!ParseOperands("a", &ops)) return false;
- address_ = ops.offset;
- break;
-
- // Advance the address.
- case DW_CFA_advance_loc1:
- if (!ParseOperands("1", &ops)) return false;
- address_ += ops.offset * cie->code_alignment_factor;
- break;
-
- // Advance the address.
- case DW_CFA_advance_loc2:
- if (!ParseOperands("2", &ops)) return false;
- address_ += ops.offset * cie->code_alignment_factor;
- break;
-
- // Advance the address.
- case DW_CFA_advance_loc4:
- if (!ParseOperands("4", &ops)) return false;
- address_ += ops.offset * cie->code_alignment_factor;
- break;
-
- // Advance the address.
- case DW_CFA_MIPS_advance_loc8:
- if (!ParseOperands("8", &ops)) return false;
- address_ += ops.offset * cie->code_alignment_factor;
- break;
-
- // Compute the CFA by adding an offset to a register.
- case DW_CFA_def_cfa:
- if (!ParseOperands("ro", &ops) ||
- !DoDefCFA(ops.register_number, ops.offset))
- return false;
- break;
-
- // Compute the CFA by adding an offset to a register.
- case DW_CFA_def_cfa_sf:
- if (!ParseOperands("rs", &ops) ||
- !DoDefCFA(ops.register_number,
- ops.signed_offset * cie->data_alignment_factor))
- return false;
- break;
-
- // Change the base register used to compute the CFA.
- case DW_CFA_def_cfa_register: {
- if (!ParseOperands("r", &ops)) return false;
- Rule *cfa_rule = rules_.CFARule();
- if (!cfa_rule) {
- if (!DoDefCFA(ops.register_number, ops.offset)) {
- reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
- return false;
- }
- } else {
- cfa_rule->SetBaseRegister(ops.register_number);
- if (!cfa_rule->Handle(handler_, address_,
- Handler::kCFARegister))
- return false;
- }
- break;
- }
-
- // Change the offset used to compute the CFA.
- case DW_CFA_def_cfa_offset:
- if (!ParseOperands("o", &ops) ||
- !DoDefCFAOffset(ops.offset))
- return false;
- break;
-
- // Change the offset used to compute the CFA.
- case DW_CFA_def_cfa_offset_sf:
- if (!ParseOperands("s", &ops) ||
- !DoDefCFAOffset(ops.signed_offset * cie->data_alignment_factor))
- return false;
- break;
-
- // Specify an expression whose value is the CFA.
- case DW_CFA_def_cfa_expression: {
- if (!ParseOperands("e", &ops))
- return false;
- Rule *rule = new ValExpressionRule(ops.expression);
- rules_.SetCFARule(rule);
- if (!rule->Handle(handler_, address_,
- Handler::kCFARegister))
- return false;
- break;
- }
-
- // The register's value cannot be recovered.
- case DW_CFA_undefined: {
- if (!ParseOperands("r", &ops) ||
- !DoRule(ops.register_number, new UndefinedRule()))
- return false;
- break;
- }
-
- // The register's value is unchanged from its value in the caller.
- case DW_CFA_same_value: {
- if (!ParseOperands("r", &ops) ||
- !DoRule(ops.register_number, new SameValueRule()))
- return false;
- break;
- }
-
- // Find a register at an offset from the CFA.
- case DW_CFA_offset_extended:
- if (!ParseOperands("ro", &ops) ||
- !DoOffset(ops.register_number,
- ops.offset * cie->data_alignment_factor))
- return false;
- break;
-
- // The register is saved at an offset from the CFA.
- case DW_CFA_offset_extended_sf:
- if (!ParseOperands("rs", &ops) ||
- !DoOffset(ops.register_number,
- ops.signed_offset * cie->data_alignment_factor))
- return false;
- break;
-
- // The register is saved at an offset from the CFA.
- case DW_CFA_GNU_negative_offset_extended:
- if (!ParseOperands("ro", &ops) ||
- !DoOffset(ops.register_number,
- -ops.offset * cie->data_alignment_factor))
- return false;
- break;
-
- // The register's value is the sum of the CFA plus an offset.
- case DW_CFA_val_offset:
- if (!ParseOperands("ro", &ops) ||
- !DoValOffset(ops.register_number,
- ops.offset * cie->data_alignment_factor))
- return false;
- break;
-
- // The register's value is the sum of the CFA plus an offset.
- case DW_CFA_val_offset_sf:
- if (!ParseOperands("rs", &ops) ||
- !DoValOffset(ops.register_number,
- ops.signed_offset * cie->data_alignment_factor))
- return false;
- break;
-
- // The register has been saved in another register.
- case DW_CFA_register: {
- if (!ParseOperands("ro", &ops) ||
- !DoRule(ops.register_number, new RegisterRule(ops.offset)))
- return false;
- break;
- }
-
- // An expression yields the address at which the register is saved.
- case DW_CFA_expression: {
- if (!ParseOperands("re", &ops) ||
- !DoRule(ops.register_number, new ExpressionRule(ops.expression)))
- return false;
- break;
- }
-
- // An expression yields the caller's value for the register.
- case DW_CFA_val_expression: {
- if (!ParseOperands("re", &ops) ||
- !DoRule(ops.register_number, new ValExpressionRule(ops.expression)))
- return false;
- break;
- }
-
- // Restore the rule established for a register by the CIE.
- case DW_CFA_restore_extended:
- if (!ParseOperands("r", &ops) ||
- !DoRestore( ops.register_number))
- return false;
- break;
-
- // Save the current set of rules on a stack.
- case DW_CFA_remember_state:
- saved_rules_.push(rules_);
- break;
-
- // Pop the current set of rules off the stack.
- case DW_CFA_restore_state: {
- if (saved_rules_.empty()) {
- reporter_->EmptyStateStack(entry_->offset, entry_->kind,
- CursorOffset());
- return false;
- }
- const RuleMap &new_rules = saved_rules_.top();
- if (rules_.CFARule() && !new_rules.CFARule()) {
- reporter_->ClearingCFARule(entry_->offset, entry_->kind,
- CursorOffset());
- return false;
- }
- rules_.HandleTransitionTo(handler_, address_, new_rules);
- rules_ = new_rules;
- saved_rules_.pop();
- break;
- }
-
- // No operation. (Padding instruction.)
- case DW_CFA_nop:
- break;
-
- // A SPARC register window save: Registers 8 through 15 (%o0-%o7)
- // are saved in registers 24 through 31 (%i0-%i7), and registers
- // 16 through 31 (%l0-%l7 and %i0-%i7) are saved at CFA offsets
- // (0-15 * the register size). The register numbers must be
- // hard-coded. A GNU extension, and not a pretty one.
- case DW_CFA_GNU_window_save: {
- // Save %o0-%o7 in %i0-%i7.
- for (int i = 8; i < 16; i++)
- if (!DoRule(i, new RegisterRule(i + 16)))
- return false;
- // Save %l0-%l7 and %i0-%i7 at the CFA.
- for (int i = 16; i < 32; i++)
- // Assume that the byte reader's address size is the same as
- // the architecture's register size. !@#%*^ hilarious.
- if (!DoRule(i, new OffsetRule(Handler::kCFARegister,
- (i - 16) * reader_->AddressSize())))
- return false;
- break;
- }
-
- // I'm not sure what this is. GDB doesn't use it for unwinding.
- case DW_CFA_GNU_args_size:
- if (!ParseOperands("o", &ops)) return false;
- break;
-
- // An opcode we don't recognize.
- default: {
- reporter_->BadInstruction(entry_->offset, entry_->kind, CursorOffset());
- return false;
- }
- }
-
- return true;
-}
-
-bool CallFrameInfo::State::DoDefCFA(unsigned base_register, long offset) {
- Rule *rule = new ValOffsetRule(base_register, offset);
- rules_.SetCFARule(rule);
- return rule->Handle(handler_, address_,
- Handler::kCFARegister);
-}
-
-bool CallFrameInfo::State::DoDefCFAOffset(long offset) {
- Rule *cfa_rule = rules_.CFARule();
- if (!cfa_rule) {
- reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
- return false;
- }
- cfa_rule->SetOffset(offset);
- return cfa_rule->Handle(handler_, address_,
- Handler::kCFARegister);
-}
-
-bool CallFrameInfo::State::DoRule(unsigned reg, Rule *rule) {
- rules_.SetRegisterRule(reg, rule);
- return rule->Handle(handler_, address_, reg);
-}
-
-bool CallFrameInfo::State::DoOffset(unsigned reg, long offset) {
- if (!rules_.CFARule()) {
- reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
- return false;
- }
- return DoRule(reg,
- new OffsetRule(Handler::kCFARegister, offset));
-}
-
-bool CallFrameInfo::State::DoValOffset(unsigned reg, long offset) {
- if (!rules_.CFARule()) {
- reporter_->NoCFARule(entry_->offset, entry_->kind, CursorOffset());
- return false;
- }
- return DoRule(reg,
- new ValOffsetRule(Handler::kCFARegister, offset));
-}
-
-bool CallFrameInfo::State::DoRestore(unsigned reg) {
- // DW_CFA_restore and DW_CFA_restore_extended don't make sense in a CIE.
- if (entry_->kind == kCIE) {
- reporter_->RestoreInCIE(entry_->offset, CursorOffset());
- return false;
- }
- Rule *rule = cie_rules_.RegisterRule(reg);
- if (!rule) {
- // This isn't really the right thing to do, but since CFI generally
- // only mentions callee-saves registers, and GCC's convention for
- // callee-saves registers is that they are unchanged, it's a good
- // approximation.
- rule = new SameValueRule();
- }
- return DoRule(reg, rule);
-}
-
-bool CallFrameInfo::ReadEntryPrologue(const uint8_t *cursor, Entry *entry) {
- const uint8_t *buffer_end = buffer_ + buffer_length_;
-
- // Initialize enough of ENTRY for use in error reporting.
- entry->offset = cursor - buffer_;
- entry->start = cursor;
- entry->kind = kUnknown;
- entry->end = NULL;
-
- // Read the initial length. This sets reader_'s offset size.
- size_t length_size;
- uint64 length = reader_->ReadInitialLength(cursor, &length_size);
- if (length_size > size_t(buffer_end - cursor))
- return ReportIncomplete(entry);
- cursor += length_size;
-
- // In a .eh_frame section, a length of zero marks the end of the series
- // of entries.
- if (length == 0 && eh_frame_) {
- entry->kind = kTerminator;
- entry->end = cursor;
- return true;
- }
-
- // Validate the length.
- if (length > size_t(buffer_end - cursor))
- return ReportIncomplete(entry);
-
- // The length is the number of bytes after the initial length field;
- // we have that position handy at this point, so compute the end
- // now. (If we're parsing 64-bit-offset DWARF on a 32-bit machine,
- // and the length didn't fit in a size_t, we would have rejected it
- // above.)
- entry->end = cursor + length;
-
- // Parse the next field: either the offset of a CIE or a CIE id.
- size_t offset_size = reader_->OffsetSize();
- if (offset_size > size_t(entry->end - cursor)) return ReportIncomplete(entry);
- entry->id = reader_->ReadOffset(cursor);
-
- // Don't advance cursor past id field yet; in .eh_frame data we need
- // the id's position to compute the section offset of an FDE's CIE.
-
- // Now we can decide what kind of entry this is.
- if (eh_frame_) {
- // In .eh_frame data, an ID of zero marks the entry as a CIE, and
- // anything else is an offset from the id field of the FDE to the start
- // of the CIE.
- if (entry->id == 0) {
- entry->kind = kCIE;
- } else {
- entry->kind = kFDE;
- // Turn the offset from the id into an offset from the buffer's start.
- entry->id = (cursor - buffer_) - entry->id;
- }
- } else {
- // In DWARF CFI data, an ID of ~0 (of the appropriate width, given the
- // offset size for the entry) marks the entry as a CIE, and anything
- // else is the offset of the CIE from the beginning of the section.
- if (offset_size == 4)
- entry->kind = (entry->id == 0xffffffff) ? kCIE : kFDE;
- else {
- assert(offset_size == 8);
- entry->kind = (entry->id == 0xffffffffffffffffULL) ? kCIE : kFDE;
- }
- }
-
- // Now advance cursor past the id.
- cursor += offset_size;
-
- // The fields specific to this kind of entry start here.
- entry->fields = cursor;
-
- entry->cie = NULL;
-
- return true;
-}
-
-bool CallFrameInfo::ReadCIEFields(CIE *cie) {
- const uint8_t *cursor = cie->fields;
- size_t len;
-
- assert(cie->kind == kCIE);
-
- // Prepare for early exit.
- cie->version = 0;
- cie->augmentation.clear();
- cie->code_alignment_factor = 0;
- cie->data_alignment_factor = 0;
- cie->return_address_register = 0;
- cie->has_z_augmentation = false;
- cie->pointer_encoding = DW_EH_PE_absptr;
- cie->instructions = 0;
-
- // Parse the version number.
- if (cie->end - cursor < 1)
- return ReportIncomplete(cie);
- cie->version = reader_->ReadOneByte(cursor);
- cursor++;
-
- // If we don't recognize the version, we can't parse any more fields of the
- // CIE. For DWARF CFI, we handle versions 1 through 3 (there was never a
- // version 2 of CFI data). For .eh_frame, we handle versions 1 and 3 as well;
- // the difference between those versions seems to be the same as for
- // .debug_frame.
- if (cie->version < 1 || cie->version > 3) {
- reporter_->UnrecognizedVersion(cie->offset, cie->version);
- return false;
- }
-
- const uint8_t *augmentation_start = cursor;
- const uint8_t *augmentation_end =
- reinterpret_cast<const uint8_t *>(memchr(augmentation_start, '\0',
- cie->end - augmentation_start));
- if (! augmentation_end) return ReportIncomplete(cie);
- cursor = augmentation_end;
- cie->augmentation = string(reinterpret_cast<const char *>(augmentation_start),
- cursor - augmentation_start);
- // Skip the terminating '\0'.
- cursor++;
-
- // Is this CFI augmented?
- if (!cie->augmentation.empty()) {
- // Is it an augmentation we recognize?
- if (cie->augmentation[0] == DW_Z_augmentation_start) {
- // Linux C++ ABI 'z' augmentation, used for exception handling data.
- cie->has_z_augmentation = true;
- } else {
- // Not an augmentation we recognize. Augmentations can have arbitrary
- // effects on the form of rest of the content, so we have to give up.
- reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation);
- return false;
- }
- }
-
- // Parse the code alignment factor.
- cie->code_alignment_factor = reader_->ReadUnsignedLEB128(cursor, &len);
- if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
- cursor += len;
-
- // Parse the data alignment factor.
- cie->data_alignment_factor = reader_->ReadSignedLEB128(cursor, &len);
- if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
- cursor += len;
-
- // Parse the return address register. This is a ubyte in version 1, and
- // a ULEB128 in version 3.
- if (cie->version == 1) {
- if (cursor >= cie->end) return ReportIncomplete(cie);
- cie->return_address_register = uint8(*cursor++);
- } else {
- cie->return_address_register = reader_->ReadUnsignedLEB128(cursor, &len);
- if (size_t(cie->end - cursor) < len) return ReportIncomplete(cie);
- cursor += len;
- }
-
- // If we have a 'z' augmentation string, find the augmentation data and
- // use the augmentation string to parse it.
- if (cie->has_z_augmentation) {
- uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &len);
- if (size_t(cie->end - cursor) < len + data_size)
- return ReportIncomplete(cie);
- cursor += len;
- const uint8_t *data = cursor;
- cursor += data_size;
- const uint8_t *data_end = cursor;
-
- cie->has_z_lsda = false;
- cie->has_z_personality = false;
- cie->has_z_signal_frame = false;
-
- // Walk the augmentation string, and extract values from the
- // augmentation data as the string directs.
- for (size_t i = 1; i < cie->augmentation.size(); i++) {
- switch (cie->augmentation[i]) {
- case DW_Z_has_LSDA:
- // The CIE's augmentation data holds the language-specific data
- // area pointer's encoding, and the FDE's augmentation data holds
- // the pointer itself.
- cie->has_z_lsda = true;
- // Fetch the LSDA encoding from the augmentation data.
- if (data >= data_end) return ReportIncomplete(cie);
- cie->lsda_encoding = DwarfPointerEncoding(*data++);
- if (!reader_->ValidEncoding(cie->lsda_encoding)) {
- reporter_->InvalidPointerEncoding(cie->offset, cie->lsda_encoding);
- return false;
- }
- // Don't check if the encoding is usable here --- we haven't
- // read the FDE's fields yet, so we're not prepared for
- // DW_EH_PE_funcrel, although that's a fine encoding for the
- // LSDA to use, since it appears in the FDE.
- break;
-
- case DW_Z_has_personality_routine:
- // The CIE's augmentation data holds the personality routine
- // pointer's encoding, followed by the pointer itself.
- cie->has_z_personality = true;
- // Fetch the personality routine pointer's encoding from the
- // augmentation data.
- if (data >= data_end) return ReportIncomplete(cie);
- cie->personality_encoding = DwarfPointerEncoding(*data++);
- if (!reader_->ValidEncoding(cie->personality_encoding)) {
- reporter_->InvalidPointerEncoding(cie->offset,
- cie->personality_encoding);
- return false;
- }
- if (!reader_->UsableEncoding(cie->personality_encoding)) {
- reporter_->UnusablePointerEncoding(cie->offset,
- cie->personality_encoding);
- return false;
- }
- // Fetch the personality routine's pointer itself from the data.
- cie->personality_address =
- reader_->ReadEncodedPointer(data, cie->personality_encoding,
- &len);
- if (len > size_t(data_end - data))
- return ReportIncomplete(cie);
- data += len;
- break;
-
- case DW_Z_has_FDE_address_encoding:
- // The CIE's augmentation data holds the pointer encoding to use
- // for addresses in the FDE.
- if (data >= data_end) return ReportIncomplete(cie);
- cie->pointer_encoding = DwarfPointerEncoding(*data++);
- if (!reader_->ValidEncoding(cie->pointer_encoding)) {
- reporter_->InvalidPointerEncoding(cie->offset,
- cie->pointer_encoding);
- return false;
- }
- if (!reader_->UsableEncoding(cie->pointer_encoding)) {
- reporter_->UnusablePointerEncoding(cie->offset,
- cie->pointer_encoding);
- return false;
- }
- break;
-
- case DW_Z_is_signal_trampoline:
- // Frames using this CIE are signal delivery frames.
- cie->has_z_signal_frame = true;
- break;
-
- default:
- // An augmentation we don't recognize.
- reporter_->UnrecognizedAugmentation(cie->offset, cie->augmentation);
- return false;
- }
- }
- }
-
- // The CIE's instructions start here.
- cie->instructions = cursor;
-
- return true;
-}
-
-bool CallFrameInfo::ReadFDEFields(FDE *fde) {
- const uint8_t *cursor = fde->fields;
- size_t size;
-
- fde->address = reader_->ReadEncodedPointer(cursor, fde->cie->pointer_encoding,
- &size);
- if (size > size_t(fde->end - cursor))
- return ReportIncomplete(fde);
- cursor += size;
- reader_->SetFunctionBase(fde->address);
-
- // For the length, we strip off the upper nybble of the encoding used for
- // the starting address.
- DwarfPointerEncoding length_encoding =
- DwarfPointerEncoding(fde->cie->pointer_encoding & 0x0f);
- fde->size = reader_->ReadEncodedPointer(cursor, length_encoding, &size);
- if (size > size_t(fde->end - cursor))
- return ReportIncomplete(fde);
- cursor += size;
-
- // If the CIE has a 'z' augmentation string, then augmentation data
- // appears here.
- if (fde->cie->has_z_augmentation) {
- uint64_t data_size = reader_->ReadUnsignedLEB128(cursor, &size);
- if (size_t(fde->end - cursor) < size + data_size)
- return ReportIncomplete(fde);
- cursor += size;
-
- // In the abstract, we should walk the augmentation string, and extract
- // items from the FDE's augmentation data as we encounter augmentation
- // string characters that specify their presence: the ordering of items
- // in the augmentation string determines the arrangement of values in
- // the augmentation data.
- //
- // In practice, there's only ever one value in FDE augmentation data
- // that we support --- the LSDA pointer --- and we have to bail if we
- // see any unrecognized augmentation string characters. So if there is
- // anything here at all, we know what it is, and where it starts.
- if (fde->cie->has_z_lsda) {
- // Check whether the LSDA's pointer encoding is usable now: only once
- // we've parsed the FDE's starting address do we call reader_->
- // SetFunctionBase, so that the DW_EH_PE_funcrel encoding becomes
- // usable.
- if (!reader_->UsableEncoding(fde->cie->lsda_encoding)) {
- reporter_->UnusablePointerEncoding(fde->cie->offset,
- fde->cie->lsda_encoding);
- return false;
- }
-
- fde->lsda_address =
- reader_->ReadEncodedPointer(cursor, fde->cie->lsda_encoding, &size);
- if (size > data_size)
- return ReportIncomplete(fde);
- // Ideally, we would also complain here if there were unconsumed
- // augmentation data.
- }
-
- cursor += data_size;
- }
-
- // The FDE's instructions start after those.
- fde->instructions = cursor;
-
- return true;
-}
-
-bool CallFrameInfo::Start() {
- const uint8_t *buffer_end = buffer_ + buffer_length_;
- const uint8_t *cursor;
- bool all_ok = true;
- const uint8_t *entry_end;
- bool ok;
-
- // Traverse all the entries in buffer_, skipping CIEs and offering
- // FDEs to the handler.
- for (cursor = buffer_; cursor < buffer_end;
- cursor = entry_end, all_ok = all_ok && ok) {
- FDE fde;
-
- // Make it easy to skip this entry with 'continue': assume that
- // things are not okay until we've checked all the data, and
- // prepare the address of the next entry.
- ok = false;
-
- // Read the entry's prologue.
- if (!ReadEntryPrologue(cursor, &fde)) {
- if (!fde.end) {
- // If we couldn't even figure out this entry's extent, then we
- // must stop processing entries altogether.
- all_ok = false;
- break;
- }
- entry_end = fde.end;
- continue;
- }
-
- // The next iteration picks up after this entry.
- entry_end = fde.end;
-
- // Did we see an .eh_frame terminating mark?
- if (fde.kind == kTerminator) {
- // If there appears to be more data left in the section after the
- // terminating mark, warn the user. But this is just a warning;
- // we leave all_ok true.
- if (fde.end < buffer_end) reporter_->EarlyEHTerminator(fde.offset);
- break;
- }
-
- // In this loop, we skip CIEs. We only parse them fully when we
- // parse an FDE that refers to them. This limits our memory
- // consumption (beyond the buffer itself) to that needed to
- // process the largest single entry.
- if (fde.kind != kFDE) {
- ok = true;
- continue;
- }
-
- // Validate the CIE pointer.
- if (fde.id > buffer_length_) {
- reporter_->CIEPointerOutOfRange(fde.offset, fde.id);
- continue;
- }
-
- CIE cie;
-
- // Parse this FDE's CIE header.
- if (!ReadEntryPrologue(buffer_ + fde.id, &cie))
- continue;
- // This had better be an actual CIE.
- if (cie.kind != kCIE) {
- reporter_->BadCIEId(fde.offset, fde.id);
- continue;
- }
- if (!ReadCIEFields(&cie))
- continue;
-
- // We now have the values that govern both the CIE and the FDE.
- cie.cie = &cie;
- fde.cie = &cie;
-
- // Parse the FDE's header.
- if (!ReadFDEFields(&fde))
- continue;
-
- // Call Entry to ask the consumer if they're interested.
- if (!handler_->Entry(fde.offset, fde.address, fde.size,
- cie.version, cie.augmentation,
- cie.return_address_register)) {
- // The handler isn't interested in this entry. That's not an error.
- ok = true;
- continue;
- }
-
- if (cie.has_z_augmentation) {
- // Report the personality routine address, if we have one.
- if (cie.has_z_personality) {
- if (!handler_
- ->PersonalityRoutine(cie.personality_address,
- IsIndirectEncoding(cie.personality_encoding)))
- continue;
- }
-
- // Report the language-specific data area address, if we have one.
- if (cie.has_z_lsda) {
- if (!handler_
- ->LanguageSpecificDataArea(fde.lsda_address,
- IsIndirectEncoding(cie.lsda_encoding)))
- continue;
- }
-
- // If this is a signal-handling frame, report that.
- if (cie.has_z_signal_frame) {
- if (!handler_->SignalHandler())
- continue;
- }
- }
-
- // Interpret the CIE's instructions, and then the FDE's instructions.
- State state(reader_, handler_, reporter_, fde.address);
- ok = state.InterpretCIE(cie) && state.InterpretFDE(fde);
-
- // Tell the ByteReader that the function start address from the
- // FDE header is no longer valid.
- reader_->ClearFunctionBase();
-
- // Report the end of the entry.
- handler_->End();
- }
-
- return all_ok;
-}
-
-const char *CallFrameInfo::KindName(EntryKind kind) {
- if (kind == CallFrameInfo::kUnknown)
- return "entry";
- else if (kind == CallFrameInfo::kCIE)
- return "common information entry";
- else if (kind == CallFrameInfo::kFDE)
- return "frame description entry";
- else {
- assert (kind == CallFrameInfo::kTerminator);
- return ".eh_frame sequence terminator";
- }
-}
-
-bool CallFrameInfo::ReportIncomplete(Entry *entry) {
- reporter_->Incomplete(entry->offset, entry->kind);
- return false;
-}
-
-void CallFrameInfo::Reporter::Incomplete(uint64 offset,
- CallFrameInfo::EntryKind kind) {
- fprintf(stderr,
- "%s: CFI %s at offset 0x%llx in '%s': entry ends early\n",
- filename_.c_str(), CallFrameInfo::KindName(kind), offset,
- section_.c_str());
-}
-
-void CallFrameInfo::Reporter::EarlyEHTerminator(uint64 offset) {
- fprintf(stderr,
- "%s: CFI at offset 0x%llx in '%s': saw end-of-data marker"
- " before end of section contents\n",
- filename_.c_str(), offset, section_.c_str());
-}
-
-void CallFrameInfo::Reporter::CIEPointerOutOfRange(uint64 offset,
- uint64 cie_offset) {
- fprintf(stderr,
- "%s: CFI frame description entry at offset 0x%llx in '%s':"
- " CIE pointer is out of range: 0x%llx\n",
- filename_.c_str(), offset, section_.c_str(), cie_offset);
-}
-
-void CallFrameInfo::Reporter::BadCIEId(uint64 offset, uint64 cie_offset) {
- fprintf(stderr,
- "%s: CFI frame description entry at offset 0x%llx in '%s':"
- " CIE pointer does not point to a CIE: 0x%llx\n",
- filename_.c_str(), offset, section_.c_str(), cie_offset);
-}
-
-void CallFrameInfo::Reporter::UnrecognizedVersion(uint64 offset, int version) {
- fprintf(stderr,
- "%s: CFI frame description entry at offset 0x%llx in '%s':"
- " CIE specifies unrecognized version: %d\n",
- filename_.c_str(), offset, section_.c_str(), version);
-}
-
-void CallFrameInfo::Reporter::UnrecognizedAugmentation(uint64 offset,
- const string &aug) {
- fprintf(stderr,
- "%s: CFI frame description entry at offset 0x%llx in '%s':"
- " CIE specifies unrecognized augmentation: '%s'\n",
- filename_.c_str(), offset, section_.c_str(), aug.c_str());
-}
-
-void CallFrameInfo::Reporter::InvalidPointerEncoding(uint64 offset,
- uint8 encoding) {
- fprintf(stderr,
- "%s: CFI common information entry at offset 0x%llx in '%s':"
- " 'z' augmentation specifies invalid pointer encoding: 0x%02x\n",
- filename_.c_str(), offset, section_.c_str(), encoding);
-}
-
-void CallFrameInfo::Reporter::UnusablePointerEncoding(uint64 offset,
- uint8 encoding) {
- fprintf(stderr,
- "%s: CFI common information entry at offset 0x%llx in '%s':"
- " 'z' augmentation specifies a pointer encoding for which"
- " we have no base address: 0x%02x\n",
- filename_.c_str(), offset, section_.c_str(), encoding);
-}
-
-void CallFrameInfo::Reporter::RestoreInCIE(uint64 offset, uint64 insn_offset) {
- fprintf(stderr,
- "%s: CFI common information entry at offset 0x%llx in '%s':"
- " the DW_CFA_restore instruction at offset 0x%llx"
- " cannot be used in a common information entry\n",
- filename_.c_str(), offset, section_.c_str(), insn_offset);
-}
-
-void CallFrameInfo::Reporter::BadInstruction(uint64 offset,
- CallFrameInfo::EntryKind kind,
- uint64 insn_offset) {
- fprintf(stderr,
- "%s: CFI %s at offset 0x%llx in section '%s':"
- " the instruction at offset 0x%llx is unrecognized\n",
- filename_.c_str(), CallFrameInfo::KindName(kind),
- offset, section_.c_str(), insn_offset);
-}
-
-void CallFrameInfo::Reporter::NoCFARule(uint64 offset,
- CallFrameInfo::EntryKind kind,
- uint64 insn_offset) {
- fprintf(stderr,
- "%s: CFI %s at offset 0x%llx in section '%s':"
- " the instruction at offset 0x%llx assumes that a CFA rule has"
- " been set, but none has been set\n",
- filename_.c_str(), CallFrameInfo::KindName(kind), offset,
- section_.c_str(), insn_offset);
-}
-
-void CallFrameInfo::Reporter::EmptyStateStack(uint64 offset,
- CallFrameInfo::EntryKind kind,
- uint64 insn_offset) {
- fprintf(stderr,
- "%s: CFI %s at offset 0x%llx in section '%s':"
- " the DW_CFA_restore_state instruction at offset 0x%llx"
- " should pop a saved state from the stack, but the stack is empty\n",
- filename_.c_str(), CallFrameInfo::KindName(kind), offset,
- section_.c_str(), insn_offset);
-}
-
-void CallFrameInfo::Reporter::ClearingCFARule(uint64 offset,
- CallFrameInfo::EntryKind kind,
- uint64 insn_offset) {
- fprintf(stderr,
- "%s: CFI %s at offset 0x%llx in section '%s':"
- " the DW_CFA_restore_state instruction at offset 0x%llx"
- " would clear the CFA rule in effect\n",
- filename_.c_str(), CallFrameInfo::KindName(kind), offset,
- section_.c_str(), insn_offset);
-}
-
-} // namespace dwarf2reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h
deleted file mode 100644
index 064c42bc8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader.h
+++ /dev/null
@@ -1,1288 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// CFI reader author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// This file contains definitions related to the DWARF2/3 reader and
-// it's handler interfaces.
-// The DWARF2/3 specification can be found at
-// http://dwarf.freestandards.org and should be considered required
-// reading if you wish to modify the implementation.
-// Only a cursory attempt is made to explain terminology that is
-// used here, as it is much better explained in the standard documents
-#ifndef COMMON_DWARF_DWARF2READER_H__
-#define COMMON_DWARF_DWARF2READER_H__
-
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-#include <memory>
-
-#include "common/dwarf/bytereader.h"
-#include "common/dwarf/dwarf2enums.h"
-#include "common/dwarf/types.h"
-#include "common/using_std_string.h"
-#include "common/dwarf/elf_reader.h"
-
-namespace dwarf2reader {
-struct LineStateMachine;
-class Dwarf2Handler;
-class LineInfoHandler;
-class DwpReader;
-
-// This maps from a string naming a section to a pair containing a
-// the data for the section, and the size of the section.
-typedef std::map<string, std::pair<const uint8_t *, uint64> > SectionMap;
-typedef std::list<std::pair<enum DwarfAttribute, enum DwarfForm> >
- AttributeList;
-typedef AttributeList::iterator AttributeIterator;
-typedef AttributeList::const_iterator ConstAttributeIterator;
-
-struct LineInfoHeader {
- uint64 total_length;
- uint16 version;
- uint64 prologue_length;
- uint8 min_insn_length; // insn stands for instructin
- bool default_is_stmt; // stmt stands for statement
- int8 line_base;
- uint8 line_range;
- uint8 opcode_base;
- // Use a pointer so that signalsafe_addr2line is able to use this structure
- // without heap allocation problem.
- std::vector<unsigned char> *std_opcode_lengths;
-};
-
-class LineInfo {
- public:
-
- // Initializes a .debug_line reader. Buffer and buffer length point
- // to the beginning and length of the line information to read.
- // Reader is a ByteReader class that has the endianness set
- // properly.
- LineInfo(const uint8_t *buffer_, uint64 buffer_length,
- ByteReader* reader, LineInfoHandler* handler);
-
- virtual ~LineInfo() {
- if (header_.std_opcode_lengths) {
- delete header_.std_opcode_lengths;
- }
- }
-
- // Start processing line info, and calling callbacks in the handler.
- // Consumes the line number information for a single compilation unit.
- // Returns the number of bytes processed.
- uint64 Start();
-
- // Process a single line info opcode at START using the state
- // machine at LSM. Return true if we should define a line using the
- // current state of the line state machine. Place the length of the
- // opcode in LEN.
- // If LSM_PASSES_PC is non-NULL, this function also checks if the lsm
- // passes the address of PC. In other words, LSM_PASSES_PC will be
- // set to true, if the following condition is met.
- //
- // lsm's old address < PC <= lsm's new address
- static bool ProcessOneOpcode(ByteReader* reader,
- LineInfoHandler* handler,
- const struct LineInfoHeader &header,
- const uint8_t *start,
- struct LineStateMachine* lsm,
- size_t* len,
- uintptr pc,
- bool *lsm_passes_pc);
-
- private:
- // Reads the DWARF2/3 header for this line info.
- void ReadHeader();
-
- // Reads the DWARF2/3 line information
- void ReadLines();
-
- // The associated handler to call processing functions in
- LineInfoHandler* handler_;
-
- // The associated ByteReader that handles endianness issues for us
- ByteReader* reader_;
-
- // A DWARF2/3 line info header. This is not the same size as
- // in the actual file, as the one in the file may have a 32 bit or
- // 64 bit lengths
-
- struct LineInfoHeader header_;
-
- // buffer is the buffer for our line info, starting at exactly where
- // the line info to read is. after_header is the place right after
- // the end of the line information header.
- const uint8_t *buffer_;
-#ifndef NDEBUG
- uint64 buffer_length_;
-#endif
- const uint8_t *after_header_;
-};
-
-// This class is the main interface between the line info reader and
-// the client. The virtual functions inside this get called for
-// interesting events that happen during line info reading. The
-// default implementation does nothing
-
-class LineInfoHandler {
- public:
- LineInfoHandler() { }
-
- virtual ~LineInfoHandler() { }
-
- // Called when we define a directory. NAME is the directory name,
- // DIR_NUM is the directory number
- virtual void DefineDir(const string& name, uint32 dir_num) { }
-
- // Called when we define a filename. NAME is the filename, FILE_NUM
- // is the file number which is -1 if the file index is the next
- // index after the last numbered index (this happens when files are
- // dynamically defined by the line program), DIR_NUM is the
- // directory index for the directory name of this file, MOD_TIME is
- // the modification time of the file, and LENGTH is the length of
- // the file
- virtual void DefineFile(const string& name, int32 file_num,
- uint32 dir_num, uint64 mod_time,
- uint64 length) { }
-
- // Called when the line info reader has a new line, address pair
- // ready for us. ADDRESS is the address of the code, LENGTH is the
- // length of its machine code in bytes, FILE_NUM is the file number
- // containing the code, LINE_NUM is the line number in that file for
- // the code, and COLUMN_NUM is the column number the code starts at,
- // if we know it (0 otherwise).
- virtual void AddLine(uint64 address, uint64 length,
- uint32 file_num, uint32 line_num, uint32 column_num) { }
-};
-
-// This class is the main interface between the reader and the
-// client. The virtual functions inside this get called for
-// interesting events that happen during DWARF2 reading.
-// The default implementation skips everything.
-class Dwarf2Handler {
- public:
- Dwarf2Handler() { }
-
- virtual ~Dwarf2Handler() { }
-
- // Start to process a compilation unit at OFFSET from the beginning of the
- // .debug_info section. Return false if you would like to skip this
- // compilation unit.
- virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version) { return false; }
-
- // When processing a skeleton compilation unit, resulting from a split
- // DWARF compilation, once the skeleton debug info has been read,
- // the reader will call this function to ask the client if it needs
- // the full debug info from the .dwo or .dwp file. Return true if
- // you need it, or false to skip processing the split debug info.
- virtual bool NeedSplitDebugInfo() { return true; }
-
- // Start to process a split compilation unit at OFFSET from the beginning of
- // the debug_info section in the .dwp/.dwo file. Return false if you would
- // like to skip this compilation unit.
- virtual bool StartSplitCompilationUnit(uint64 offset,
- uint64 cu_length) { return false; }
-
- // Start to process a DIE at OFFSET from the beginning of the .debug_info
- // section. Return false if you would like to skip this DIE.
- virtual bool StartDIE(uint64 offset, enum DwarfTag tag) { return false; }
-
- // Called when we have an attribute with unsigned data to give to our
- // handler. The attribute is for the DIE at OFFSET from the beginning of the
- // .debug_info section. Its name is ATTR, its form is FORM, and its value is
- // DATA.
- virtual void ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) { }
-
- // Called when we have an attribute with signed data to give to our handler.
- // The attribute is for the DIE at OFFSET from the beginning of the
- // .debug_info section. Its name is ATTR, its form is FORM, and its value is
- // DATA.
- virtual void ProcessAttributeSigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) { }
-
- // Called when we have an attribute whose value is a reference to
- // another DIE. The attribute belongs to the DIE at OFFSET from the
- // beginning of the .debug_info section. Its name is ATTR, its form
- // is FORM, and the offset of the DIE being referred to from the
- // beginning of the .debug_info section is DATA.
- virtual void ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) { }
-
- // Called when we have an attribute with a buffer of data to give to our
- // handler. The attribute is for the DIE at OFFSET from the beginning of the
- // .debug_info section. Its name is ATTR, its form is FORM, DATA points to
- // the buffer's contents, and its length in bytes is LENGTH. The buffer is
- // owned by the caller, not the callee, and may not persist for very long.
- // If you want the data to be available later, it needs to be copied.
- virtual void ProcessAttributeBuffer(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t *data,
- uint64 len) { }
-
- // Called when we have an attribute with string data to give to our handler.
- // The attribute is for the DIE at OFFSET from the beginning of the
- // .debug_info section. Its name is ATTR, its form is FORM, and its value is
- // DATA.
- virtual void ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string& data) { }
-
- // Called when we have an attribute whose value is the 64-bit signature
- // of a type unit in the .debug_types section. OFFSET is the offset of
- // the DIE whose attribute we're reporting. ATTR and FORM are the
- // attribute's name and form. SIGNATURE is the type unit's signature.
- virtual void ProcessAttributeSignature(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 signature) { }
-
- // Called when finished processing the DIE at OFFSET.
- // Because DWARF2/3 specifies a tree of DIEs, you may get starts
- // before ends of the previous DIE, as we process children before
- // ending the parent.
- virtual void EndDIE(uint64 offset) { }
-
-};
-
-// The base of DWARF2/3 debug info is a DIE (Debugging Information
-// Entry.
-// DWARF groups DIE's into a tree and calls the root of this tree a
-// "compilation unit". Most of the time, there is one compilation
-// unit in the .debug_info section for each file that had debug info
-// generated.
-// Each DIE consists of
-
-// 1. a tag specifying a thing that is being described (ie
-// DW_TAG_subprogram for functions, DW_TAG_variable for variables, etc
-// 2. attributes (such as DW_AT_location for location in memory,
-// DW_AT_name for name), and data for each attribute.
-// 3. A flag saying whether the DIE has children or not
-
-// In order to gain some amount of compression, the format of
-// each DIE (tag name, attributes and data forms for the attributes)
-// are stored in a separate table called the "abbreviation table".
-// This is done because a large number of DIEs have the exact same tag
-// and list of attributes, but different data for those attributes.
-// As a result, the .debug_info section is just a stream of data, and
-// requires reading of the .debug_abbrev section to say what the data
-// means.
-
-// As a warning to the user, it should be noted that the reason for
-// using absolute offsets from the beginning of .debug_info is that
-// DWARF2/3 supports referencing DIE's from other DIE's by their offset
-// from either the current compilation unit start, *or* the beginning
-// of the .debug_info section. This means it is possible to reference
-// a DIE in one compilation unit from a DIE in another compilation
-// unit. This style of reference is usually used to eliminate
-// duplicated information that occurs across compilation
-// units, such as base types, etc. GCC 3.4+ support this with
-// -feliminate-dwarf2-dups. Other toolchains will sometimes do
-// duplicate elimination in the linker.
-
-class CompilationUnit {
- public:
-
- // Initialize a compilation unit. This requires a map of sections,
- // the offset of this compilation unit in the .debug_info section, a
- // ByteReader, and a Dwarf2Handler class to call callbacks in.
- CompilationUnit(const string& path, const SectionMap& sections, uint64 offset,
- ByteReader* reader, Dwarf2Handler* handler);
- virtual ~CompilationUnit() {
- if (abbrevs_) delete abbrevs_;
- }
-
- // Initialize a compilation unit from a .dwo or .dwp file.
- // In this case, we need the .debug_addr section from the
- // executable file that contains the corresponding skeleton
- // compilation unit. We also inherit the Dwarf2Handler from
- // the executable file, and call it as if we were still
- // processing the original compilation unit.
- void SetSplitDwarf(const uint8_t* addr_buffer, uint64 addr_buffer_length,
- uint64 addr_base, uint64 ranges_base, uint64 dwo_id);
-
- // Begin reading a Dwarf2 compilation unit, and calling the
- // callbacks in the Dwarf2Handler
-
- // Return the full length of the compilation unit, including
- // headers. This plus the starting offset passed to the constructor
- // is the offset of the end of the compilation unit --- and the
- // start of the next compilation unit, if there is one.
- uint64 Start();
-
- private:
-
- // This struct represents a single DWARF2/3 abbreviation
- // The abbreviation tells how to read a DWARF2/3 DIE, and consist of a
- // tag and a list of attributes, as well as the data form of each attribute.
- struct Abbrev {
- uint64 number;
- enum DwarfTag tag;
- bool has_children;
- AttributeList attributes;
- };
-
- // A DWARF2/3 compilation unit header. This is not the same size as
- // in the actual file, as the one in the file may have a 32 bit or
- // 64 bit length.
- struct CompilationUnitHeader {
- uint64 length;
- uint16 version;
- uint64 abbrev_offset;
- uint8 address_size;
- } header_;
-
- // Reads the DWARF2/3 header for this compilation unit.
- void ReadHeader();
-
- // Reads the DWARF2/3 abbreviations for this compilation unit
- void ReadAbbrevs();
-
- // Processes a single DIE for this compilation unit and return a new
- // pointer just past the end of it
- const uint8_t *ProcessDIE(uint64 dieoffset,
- const uint8_t *start,
- const Abbrev& abbrev);
-
- // Processes a single attribute and return a new pointer just past the
- // end of it
- const uint8_t *ProcessAttribute(uint64 dieoffset,
- const uint8_t *start,
- enum DwarfAttribute attr,
- enum DwarfForm form);
-
- // Called when we have an attribute with unsigned data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of compilation unit, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA.
- // If we see a DW_AT_GNU_dwo_id attribute, save the value so that
- // we can find the debug info in a .dwo or .dwp file.
- void ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- if (attr == DW_AT_GNU_dwo_id) {
- dwo_id_ = data;
- }
- else if (attr == DW_AT_GNU_addr_base) {
- addr_base_ = data;
- }
- else if (attr == DW_AT_GNU_ranges_base) {
- ranges_base_ = data;
- }
- // TODO(yunlian): When we add DW_AT_ranges_base from DWARF-5,
- // that base will apply to DW_AT_ranges attributes in the
- // skeleton CU as well as in the .dwo/.dwp files.
- else if (attr == DW_AT_ranges && is_split_dwarf_) {
- data += ranges_base_;
- }
- handler_->ProcessAttributeUnsigned(offset, attr, form, data);
- }
-
- // Called when we have an attribute with signed data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of compilation unit, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA.
- void ProcessAttributeSigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) {
- handler_->ProcessAttributeSigned(offset, attr, form, data);
- }
-
- // Called when we have an attribute with a buffer of data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of compilation unit, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA, and the
- // length of the buffer is LENGTH.
- void ProcessAttributeBuffer(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t* data,
- uint64 len) {
- handler_->ProcessAttributeBuffer(offset, attr, form, data, len);
- }
-
- // Called when we have an attribute with string data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of compilation unit, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA.
- // If we see a DW_AT_GNU_dwo_name attribute, save the value so
- // that we can find the debug info in a .dwo or .dwp file.
- void ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const char* data) {
- if (attr == DW_AT_GNU_dwo_name)
- dwo_name_ = data;
- handler_->ProcessAttributeString(offset, attr, form, data);
- }
-
- // Processes all DIEs for this compilation unit
- void ProcessDIEs();
-
- // Skips the die with attributes specified in ABBREV starting at
- // START, and return the new place to position the stream to.
- const uint8_t *SkipDIE(const uint8_t *start, const Abbrev& abbrev);
-
- // Skips the attribute starting at START, with FORM, and return the
- // new place to position the stream to.
- const uint8_t *SkipAttribute(const uint8_t *start, enum DwarfForm form);
-
- // Process the actual debug information in a split DWARF file.
- void ProcessSplitDwarf();
-
- // Read the debug sections from a .dwo file.
- void ReadDebugSectionsFromDwo(ElfReader* elf_reader,
- SectionMap* sections);
-
- // Path of the file containing the debug information.
- const string path_;
-
- // Offset from section start is the offset of this compilation unit
- // from the beginning of the .debug_info section.
- uint64 offset_from_section_start_;
-
- // buffer is the buffer for our CU, starting at .debug_info + offset
- // passed in from constructor.
- // after_header points to right after the compilation unit header.
- const uint8_t *buffer_;
- uint64 buffer_length_;
- const uint8_t *after_header_;
-
- // The associated ByteReader that handles endianness issues for us
- ByteReader* reader_;
-
- // The map of sections in our file to buffers containing their data
- const SectionMap& sections_;
-
- // The associated handler to call processing functions in
- Dwarf2Handler* handler_;
-
- // Set of DWARF2/3 abbreviations for this compilation unit. Indexed
- // by abbreviation number, which means that abbrevs_[0] is not
- // valid.
- std::vector<Abbrev>* abbrevs_;
-
- // String section buffer and length, if we have a string section.
- // This is here to avoid doing a section lookup for strings in
- // ProcessAttribute, which is in the hot path for DWARF2 reading.
- const uint8_t *string_buffer_;
- uint64 string_buffer_length_;
-
- // String offsets section buffer and length, if we have a string offsets
- // section (.debug_str_offsets or .debug_str_offsets.dwo).
- const uint8_t* str_offsets_buffer_;
- uint64 str_offsets_buffer_length_;
-
- // Address section buffer and length, if we have an address section
- // (.debug_addr).
- const uint8_t* addr_buffer_;
- uint64 addr_buffer_length_;
-
- // Flag indicating whether this compilation unit is part of a .dwo
- // or .dwp file. If true, we are reading this unit because a
- // skeleton compilation unit in an executable file had a
- // DW_AT_GNU_dwo_name or DW_AT_GNU_dwo_id attribute.
- // In a .dwo file, we expect the string offsets section to
- // have a ".dwo" suffix, and we will use the ".debug_addr" section
- // associated with the skeleton compilation unit.
- bool is_split_dwarf_;
-
- // The value of the DW_AT_GNU_dwo_id attribute, if any.
- uint64 dwo_id_;
-
- // The value of the DW_AT_GNU_dwo_name attribute, if any.
- const char* dwo_name_;
-
- // If this is a split DWARF CU, the value of the DW_AT_GNU_dwo_id attribute
- // from the skeleton CU.
- uint64 skeleton_dwo_id_;
-
- // The value of the DW_AT_GNU_ranges_base attribute, if any.
- uint64 ranges_base_;
-
- // The value of the DW_AT_GNU_addr_base attribute, if any.
- uint64 addr_base_;
-
- // True if we have already looked for a .dwp file.
- bool have_checked_for_dwp_;
-
- // Path to the .dwp file.
- string dwp_path_;
-
- // ByteReader for the DWP file.
- std::unique_ptr<ByteReader> dwp_byte_reader_;
-
- // DWP reader.
- std::unique_ptr<DwpReader> dwp_reader_;
-};
-
-// A Reader for a .dwp file. Supports the fetching of DWARF debug
-// info for a given dwo_id.
-//
-// There are two versions of .dwp files. In both versions, the
-// .dwp file is an ELF file containing only debug sections.
-// In Version 1, the file contains many copies of each debug
-// section, one for each .dwo file that is packaged in the .dwp
-// file, and the .debug_cu_index section maps from the dwo_id
-// to a set of section indexes. In Version 2, the file contains
-// one of each debug section, and the .debug_cu_index section
-// maps from the dwo_id to a set of offsets and lengths that
-// identify each .dwo file's contribution to the larger sections.
-
-class DwpReader {
- public:
- DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader);
-
- ~DwpReader();
-
- // Read the CU index and initialize data members.
- void Initialize();
-
- // Read the debug sections for the given dwo_id.
- void ReadDebugSectionsForCU(uint64 dwo_id, SectionMap* sections);
-
- private:
- // Search a v1 hash table for "dwo_id". Returns the slot index
- // where the dwo_id was found, or -1 if it was not found.
- int LookupCU(uint64 dwo_id);
-
- // Search a v2 hash table for "dwo_id". Returns the row index
- // in the offsets and sizes tables, or 0 if it was not found.
- uint32 LookupCUv2(uint64 dwo_id);
-
- // The ELF reader for the .dwp file.
- ElfReader* elf_reader_;
-
- // The ByteReader for the .dwp file.
- const ByteReader& byte_reader_;
-
- // Pointer to the .debug_cu_index section.
- const char* cu_index_;
-
- // Size of the .debug_cu_index section.
- size_t cu_index_size_;
-
- // Pointer to the .debug_str.dwo section.
- const char* string_buffer_;
-
- // Size of the .debug_str.dwo section.
- size_t string_buffer_size_;
-
- // Version of the .dwp file. We support versions 1 and 2 currently.
- int version_;
-
- // Number of columns in the section tables (version 2).
- unsigned int ncolumns_;
-
- // Number of units in the section tables (version 2).
- unsigned int nunits_;
-
- // Number of slots in the hash table.
- unsigned int nslots_;
-
- // Pointer to the beginning of the hash table.
- const char* phash_;
-
- // Pointer to the beginning of the index table.
- const char* pindex_;
-
- // Pointer to the beginning of the section index pool (version 1).
- const char* shndx_pool_;
-
- // Pointer to the beginning of the section offset table (version 2).
- const char* offset_table_;
-
- // Pointer to the beginning of the section size table (version 2).
- const char* size_table_;
-
- // Contents of the sections of interest (version 2).
- const char* abbrev_data_;
- size_t abbrev_size_;
- const char* info_data_;
- size_t info_size_;
- const char* str_offsets_data_;
- size_t str_offsets_size_;
-};
-
-// This class is a reader for DWARF's Call Frame Information. CFI
-// describes how to unwind stack frames --- even for functions that do
-// not follow fixed conventions for saving registers, whose frame size
-// varies as they execute, etc.
-//
-// CFI describes, at each machine instruction, how to compute the
-// stack frame's base address, how to find the return address, and
-// where to find the saved values of the caller's registers (if the
-// callee has stashed them somewhere to free up the registers for its
-// own use).
-//
-// For example, suppose we have a function whose machine code looks
-// like this (imagine an assembly language that looks like C, for a
-// machine with 32-bit registers, and a stack that grows towards lower
-// addresses):
-//
-// func: ; entry point; return address at sp
-// func+0: sp = sp - 16 ; allocate space for stack frame
-// func+1: sp[12] = r0 ; save r0 at sp+12
-// ... ; other code, not frame-related
-// func+10: sp -= 4; *sp = x ; push some x on the stack
-// ... ; other code, not frame-related
-// func+20: r0 = sp[16] ; restore saved r0
-// func+21: sp += 20 ; pop whole stack frame
-// func+22: pc = *sp; sp += 4 ; pop return address and jump to it
-//
-// DWARF CFI is (a very compressed representation of) a table with a
-// row for each machine instruction address and a column for each
-// register showing how to restore it, if possible.
-//
-// A special column named "CFA", for "Canonical Frame Address", tells how
-// to compute the base address of the frame; registers' entries may
-// refer to the CFA in describing where the registers are saved.
-//
-// Another special column, named "RA", represents the return address.
-//
-// For example, here is a complete (uncompressed) table describing the
-// function above:
-//
-// insn cfa r0 r1 ... ra
-// =======================================
-// func+0: sp cfa[0]
-// func+1: sp+16 cfa[0]
-// func+2: sp+16 cfa[-4] cfa[0]
-// func+11: sp+20 cfa[-4] cfa[0]
-// func+21: sp+20 cfa[0]
-// func+22: sp cfa[0]
-//
-// Some things to note here:
-//
-// - Each row describes the state of affairs *before* executing the
-// instruction at the given address. Thus, the row for func+0
-// describes the state before we allocate the stack frame. In the
-// next row, the formula for computing the CFA has changed,
-// reflecting that allocation.
-//
-// - The other entries are written in terms of the CFA; this allows
-// them to remain unchanged as the stack pointer gets bumped around.
-// For example, the rule for recovering the return address (the "ra"
-// column) remains unchanged throughout the function, even as the
-// stack pointer takes on three different offsets from the return
-// address.
-//
-// - Although we haven't shown it, most calling conventions designate
-// "callee-saves" and "caller-saves" registers. The callee must
-// preserve the values of callee-saves registers; if it uses them,
-// it must save their original values somewhere, and restore them
-// before it returns. In contrast, the callee is free to trash
-// caller-saves registers; if the callee uses these, it will
-// probably not bother to save them anywhere, and the CFI will
-// probably mark their values as "unrecoverable".
-//
-// (However, since the caller cannot assume the callee was going to
-// save them, caller-saves registers are probably dead in the caller
-// anyway, so compilers usually don't generate CFA for caller-saves
-// registers.)
-//
-// - Exactly where the CFA points is a matter of convention that
-// depends on the architecture and ABI in use. In the example, the
-// CFA is the value the stack pointer had upon entry to the
-// function, pointing at the saved return address. But on the x86,
-// the call frame information generated by GCC follows the
-// convention that the CFA is the address *after* the saved return
-// address.
-//
-// But by definition, the CFA remains constant throughout the
-// lifetime of the frame. This makes it a useful value for other
-// columns to refer to. It is also gives debuggers a useful handle
-// for identifying a frame.
-//
-// If you look at the table above, you'll notice that a given entry is
-// often the same as the one immediately above it: most instructions
-// change only one or two aspects of the stack frame, if they affect
-// it at all. The DWARF format takes advantage of this fact, and
-// reduces the size of the data by mentioning only the addresses and
-// columns at which changes take place. So for the above, DWARF CFI
-// data would only actually mention the following:
-//
-// insn cfa r0 r1 ... ra
-// =======================================
-// func+0: sp cfa[0]
-// func+1: sp+16
-// func+2: cfa[-4]
-// func+11: sp+20
-// func+21: r0
-// func+22: sp
-//
-// In fact, this is the way the parser reports CFI to the consumer: as
-// a series of statements of the form, "At address X, column Y changed
-// to Z," and related conventions for describing the initial state.
-//
-// Naturally, it would be impractical to have to scan the entire
-// program's CFI, noting changes as we go, just to recover the
-// unwinding rules in effect at one particular instruction. To avoid
-// this, CFI data is grouped into "entries", each of which covers a
-// specified range of addresses and begins with a complete statement
-// of the rules for all recoverable registers at that starting
-// address. Each entry typically covers a single function.
-//
-// Thus, to compute the contents of a given row of the table --- that
-// is, rules for recovering the CFA, RA, and registers at a given
-// instruction --- the consumer should find the entry that covers that
-// instruction's address, start with the initial state supplied at the
-// beginning of the entry, and work forward until it has processed all
-// the changes up to and including those for the present instruction.
-//
-// There are seven kinds of rules that can appear in an entry of the
-// table:
-//
-// - "undefined": The given register is not preserved by the callee;
-// its value cannot be recovered.
-//
-// - "same value": This register has the same value it did in the callee.
-//
-// - offset(N): The register is saved at offset N from the CFA.
-//
-// - val_offset(N): The value the register had in the caller is the
-// CFA plus offset N. (This is usually only useful for describing
-// the stack pointer.)
-//
-// - register(R): The register's value was saved in another register R.
-//
-// - expression(E): Evaluating the DWARF expression E using the
-// current frame's registers' values yields the address at which the
-// register was saved.
-//
-// - val_expression(E): Evaluating the DWARF expression E using the
-// current frame's registers' values yields the value the register
-// had in the caller.
-
-class CallFrameInfo {
- public:
- // The different kinds of entries one finds in CFI. Used internally,
- // and for error reporting.
- enum EntryKind { kUnknown, kCIE, kFDE, kTerminator };
-
- // The handler class to which the parser hands the parsed call frame
- // information. Defined below.
- class Handler;
-
- // A reporter class, which CallFrameInfo uses to report errors
- // encountered while parsing call frame information. Defined below.
- class Reporter;
-
- // Create a DWARF CFI parser. BUFFER points to the contents of the
- // .debug_frame section to parse; BUFFER_LENGTH is its length in bytes.
- // REPORTER is an error reporter the parser should use to report
- // problems. READER is a ByteReader instance that has the endianness and
- // address size set properly. Report the data we find to HANDLER.
- //
- // This class can also parse Linux C++ exception handling data, as found
- // in '.eh_frame' sections. This data is a variant of DWARF CFI that is
- // placed in loadable segments so that it is present in the program's
- // address space, and is interpreted by the C++ runtime to search the
- // call stack for a handler interested in the exception being thrown,
- // actually pop the frames, and find cleanup code to run.
- //
- // There are two differences between the call frame information described
- // in the DWARF standard and the exception handling data Linux places in
- // the .eh_frame section:
- //
- // - Exception handling data uses uses a different format for call frame
- // information entry headers. The distinguished CIE id, the way FDEs
- // refer to their CIEs, and the way the end of the series of entries is
- // determined are all slightly different.
- //
- // If the constructor's EH_FRAME argument is true, then the
- // CallFrameInfo parses the entry headers as Linux C++ exception
- // handling data. If EH_FRAME is false or omitted, the CallFrameInfo
- // parses standard DWARF call frame information.
- //
- // - Linux C++ exception handling data uses CIE augmentation strings
- // beginning with 'z' to specify the presence of additional data after
- // the CIE and FDE headers and special encodings used for addresses in
- // frame description entries.
- //
- // CallFrameInfo can handle 'z' augmentations in either DWARF CFI or
- // exception handling data if you have supplied READER with the base
- // addresses needed to interpret the pointer encodings that 'z'
- // augmentations can specify. See the ByteReader interface for details
- // about the base addresses. See the CallFrameInfo::Handler interface
- // for details about the additional information one might find in
- // 'z'-augmented data.
- //
- // Thus:
- //
- // - If you are parsing standard DWARF CFI, as found in a .debug_frame
- // section, you should pass false for the EH_FRAME argument, or omit
- // it, and you need not worry about providing READER with the
- // additional base addresses.
- //
- // - If you want to parse Linux C++ exception handling data from a
- // .eh_frame section, you should pass EH_FRAME as true, and call
- // READER's Set*Base member functions before calling our Start method.
- //
- // - If you want to parse DWARF CFI that uses the 'z' augmentations
- // (although I don't think any toolchain ever emits such data), you
- // could pass false for EH_FRAME, but call READER's Set*Base members.
- //
- // The extensions the Linux C++ ABI makes to DWARF for exception
- // handling are described here, rather poorly:
- // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
- // http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
- //
- // The mechanics of C++ exception handling, personality routines,
- // and language-specific data areas are described here, rather nicely:
- // http://www.codesourcery.com/public/cxx-abi/abi-eh.html
- CallFrameInfo(const uint8_t *buffer, size_t buffer_length,
- ByteReader *reader, Handler *handler, Reporter *reporter,
- bool eh_frame = false)
- : buffer_(buffer), buffer_length_(buffer_length),
- reader_(reader), handler_(handler), reporter_(reporter),
- eh_frame_(eh_frame) { }
-
- ~CallFrameInfo() { }
-
- // Parse the entries in BUFFER, reporting what we find to HANDLER.
- // Return true if we reach the end of the section successfully, or
- // false if we encounter an error.
- bool Start();
-
- // Return the textual name of KIND. For error reporting.
- static const char *KindName(EntryKind kind);
-
- private:
-
- struct CIE;
-
- // A CFI entry, either an FDE or a CIE.
- struct Entry {
- // The starting offset of the entry in the section, for error
- // reporting.
- size_t offset;
-
- // The start of this entry in the buffer.
- const uint8_t *start;
-
- // Which kind of entry this is.
- //
- // We want to be able to use this for error reporting even while we're
- // in the midst of parsing. Error reporting code may assume that kind,
- // offset, and start fields are valid, although kind may be kUnknown.
- EntryKind kind;
-
- // The end of this entry's common prologue (initial length and id), and
- // the start of this entry's kind-specific fields.
- const uint8_t *fields;
-
- // The start of this entry's instructions.
- const uint8_t *instructions;
-
- // The address past the entry's last byte in the buffer. (Note that
- // since offset points to the entry's initial length field, and the
- // length field is the number of bytes after that field, this is not
- // simply buffer_ + offset + length.)
- const uint8_t *end;
-
- // For both DWARF CFI and .eh_frame sections, this is the CIE id in a
- // CIE, and the offset of the associated CIE in an FDE.
- uint64 id;
-
- // The CIE that applies to this entry, if we've parsed it. If this is a
- // CIE, then this field points to this structure.
- CIE *cie;
- };
-
- // A common information entry (CIE).
- struct CIE: public Entry {
- uint8 version; // CFI data version number
- string augmentation; // vendor format extension markers
- uint64 code_alignment_factor; // scale for code address adjustments
- int data_alignment_factor; // scale for stack pointer adjustments
- unsigned return_address_register; // which register holds the return addr
-
- // True if this CIE includes Linux C++ ABI 'z' augmentation data.
- bool has_z_augmentation;
-
- // Parsed 'z' augmentation data. These are meaningful only if
- // has_z_augmentation is true.
- bool has_z_lsda; // The 'z' augmentation included 'L'.
- bool has_z_personality; // The 'z' augmentation included 'P'.
- bool has_z_signal_frame; // The 'z' augmentation included 'S'.
-
- // If has_z_lsda is true, this is the encoding to be used for language-
- // specific data area pointers in FDEs.
- DwarfPointerEncoding lsda_encoding;
-
- // If has_z_personality is true, this is the encoding used for the
- // personality routine pointer in the augmentation data.
- DwarfPointerEncoding personality_encoding;
-
- // If has_z_personality is true, this is the address of the personality
- // routine --- or, if personality_encoding & DW_EH_PE_indirect, the
- // address where the personality routine's address is stored.
- uint64 personality_address;
-
- // This is the encoding used for addresses in the FDE header and
- // in DW_CFA_set_loc instructions. This is always valid, whether
- // or not we saw a 'z' augmentation string; its default value is
- // DW_EH_PE_absptr, which is what normal DWARF CFI uses.
- DwarfPointerEncoding pointer_encoding;
- };
-
- // A frame description entry (FDE).
- struct FDE: public Entry {
- uint64 address; // start address of described code
- uint64 size; // size of described code, in bytes
-
- // If cie->has_z_lsda is true, then this is the language-specific data
- // area's address --- or its address's address, if cie->lsda_encoding
- // has the DW_EH_PE_indirect bit set.
- uint64 lsda_address;
- };
-
- // Internal use.
- class Rule;
- class UndefinedRule;
- class SameValueRule;
- class OffsetRule;
- class ValOffsetRule;
- class RegisterRule;
- class ExpressionRule;
- class ValExpressionRule;
- class RuleMap;
- class State;
-
- // Parse the initial length and id of a CFI entry, either a CIE, an FDE,
- // or a .eh_frame end-of-data mark. CURSOR points to the beginning of the
- // data to parse. On success, populate ENTRY as appropriate, and return
- // true. On failure, report the problem, and return false. Even if we
- // return false, set ENTRY->end to the first byte after the entry if we
- // were able to figure that out, or NULL if we weren't.
- bool ReadEntryPrologue(const uint8_t *cursor, Entry *entry);
-
- // Parse the fields of a CIE after the entry prologue, including any 'z'
- // augmentation data. Assume that the 'Entry' fields of CIE are
- // populated; use CIE->fields and CIE->end as the start and limit for
- // parsing. On success, populate the rest of *CIE, and return true; on
- // failure, report the problem and return false.
- bool ReadCIEFields(CIE *cie);
-
- // Parse the fields of an FDE after the entry prologue, including any 'z'
- // augmentation data. Assume that the 'Entry' fields of *FDE are
- // initialized; use FDE->fields and FDE->end as the start and limit for
- // parsing. Assume that FDE->cie is fully initialized. On success,
- // populate the rest of *FDE, and return true; on failure, report the
- // problem and return false.
- bool ReadFDEFields(FDE *fde);
-
- // Report that ENTRY is incomplete, and return false. This is just a
- // trivial wrapper for invoking reporter_->Incomplete; it provides a
- // little brevity.
- bool ReportIncomplete(Entry *entry);
-
- // Return true if ENCODING has the DW_EH_PE_indirect bit set.
- static bool IsIndirectEncoding(DwarfPointerEncoding encoding) {
- return encoding & DW_EH_PE_indirect;
- }
-
- // The contents of the DWARF .debug_info section we're parsing.
- const uint8_t *buffer_;
- size_t buffer_length_;
-
- // For reading multi-byte values with the appropriate endianness.
- ByteReader *reader_;
-
- // The handler to which we should report the data we find.
- Handler *handler_;
-
- // For reporting problems in the info we're parsing.
- Reporter *reporter_;
-
- // True if we are processing .eh_frame-format data.
- bool eh_frame_;
-};
-
-// The handler class for CallFrameInfo. The a CFI parser calls the
-// member functions of a handler object to report the data it finds.
-class CallFrameInfo::Handler {
- public:
- // The pseudo-register number for the canonical frame address.
- enum { kCFARegister = -1 };
-
- Handler() { }
- virtual ~Handler() { }
-
- // The parser has found CFI for the machine code at ADDRESS,
- // extending for LENGTH bytes. OFFSET is the offset of the frame
- // description entry in the section, for use in error messages.
- // VERSION is the version number of the CFI format. AUGMENTATION is
- // a string describing any producer-specific extensions present in
- // the data. RETURN_ADDRESS is the number of the register that holds
- // the address to which the function should return.
- //
- // Entry should return true to process this CFI, or false to skip to
- // the next entry.
- //
- // The parser invokes Entry for each Frame Description Entry (FDE)
- // it finds. The parser doesn't report Common Information Entries
- // to the handler explicitly; instead, if the handler elects to
- // process a given FDE, the parser reiterates the appropriate CIE's
- // contents at the beginning of the FDE's rules.
- virtual bool Entry(size_t offset, uint64 address, uint64 length,
- uint8 version, const string &augmentation,
- unsigned return_address) = 0;
-
- // When the Entry function returns true, the parser calls these
- // handler functions repeatedly to describe the rules for recovering
- // registers at each instruction in the given range of machine code.
- // Immediately after a call to Entry, the handler should assume that
- // the rule for each callee-saves register is "unchanged" --- that
- // is, that the register still has the value it had in the caller.
- //
- // If a *Rule function returns true, we continue processing this entry's
- // instructions. If a *Rule function returns false, we stop evaluating
- // instructions, and skip to the next entry. Either way, we call End
- // before going on to the next entry.
- //
- // In all of these functions, if the REG parameter is kCFARegister, then
- // the rule describes how to find the canonical frame address.
- // kCFARegister may be passed as a BASE_REGISTER argument, meaning that
- // the canonical frame address should be used as the base address for the
- // computation. All other REG values will be positive.
-
- // At ADDRESS, register REG's value is not recoverable.
- virtual bool UndefinedRule(uint64 address, int reg) = 0;
-
- // At ADDRESS, register REG's value is the same as that it had in
- // the caller.
- virtual bool SameValueRule(uint64 address, int reg) = 0;
-
- // At ADDRESS, register REG has been saved at offset OFFSET from
- // BASE_REGISTER.
- virtual bool OffsetRule(uint64 address, int reg,
- int base_register, long offset) = 0;
-
- // At ADDRESS, the caller's value of register REG is the current
- // value of BASE_REGISTER plus OFFSET. (This rule doesn't provide an
- // address at which the register's value is saved.)
- virtual bool ValOffsetRule(uint64 address, int reg,
- int base_register, long offset) = 0;
-
- // At ADDRESS, register REG has been saved in BASE_REGISTER. This differs
- // from ValOffsetRule(ADDRESS, REG, BASE_REGISTER, 0), in that
- // BASE_REGISTER is the "home" for REG's saved value: if you want to
- // assign to a variable whose home is REG in the calling frame, you
- // should put the value in BASE_REGISTER.
- virtual bool RegisterRule(uint64 address, int reg, int base_register) = 0;
-
- // At ADDRESS, the DWARF expression EXPRESSION yields the address at
- // which REG was saved.
- virtual bool ExpressionRule(uint64 address, int reg,
- const string &expression) = 0;
-
- // At ADDRESS, the DWARF expression EXPRESSION yields the caller's
- // value for REG. (This rule doesn't provide an address at which the
- // register's value is saved.)
- virtual bool ValExpressionRule(uint64 address, int reg,
- const string &expression) = 0;
-
- // Indicate that the rules for the address range reported by the
- // last call to Entry are complete. End should return true if
- // everything is okay, or false if an error has occurred and parsing
- // should stop.
- virtual bool End() = 0;
-
- // Handler functions for Linux C++ exception handling data. These are
- // only called if the data includes 'z' augmentation strings.
-
- // The Linux C++ ABI uses an extension of the DWARF CFI format to
- // walk the stack to propagate exceptions from the throw to the
- // appropriate catch, and do the appropriate cleanups along the way.
- // CFI entries used for exception handling have two additional data
- // associated with them:
- //
- // - The "language-specific data area" describes which exception
- // types the function has 'catch' clauses for, and indicates how
- // to go about re-entering the function at the appropriate catch
- // clause. If the exception is not caught, it describes the
- // destructors that must run before the frame is popped.
- //
- // - The "personality routine" is responsible for interpreting the
- // language-specific data area's contents, and deciding whether
- // the exception should continue to propagate down the stack,
- // perhaps after doing some cleanup for this frame, or whether the
- // exception will be caught here.
- //
- // In principle, the language-specific data area is opaque to
- // everybody but the personality routine. In practice, these values
- // may be useful or interesting to readers with extra context, and
- // we have to at least skip them anyway, so we might as well report
- // them to the handler.
-
- // This entry's exception handling personality routine's address is
- // ADDRESS. If INDIRECT is true, then ADDRESS is the address at
- // which the routine's address is stored. The default definition for
- // this handler function simply returns true, allowing parsing of
- // the entry to continue.
- virtual bool PersonalityRoutine(uint64 address, bool indirect) {
- return true;
- }
-
- // This entry's language-specific data area (LSDA) is located at
- // ADDRESS. If INDIRECT is true, then ADDRESS is the address at
- // which the area's address is stored. The default definition for
- // this handler function simply returns true, allowing parsing of
- // the entry to continue.
- virtual bool LanguageSpecificDataArea(uint64 address, bool indirect) {
- return true;
- }
-
- // This entry describes a signal trampoline --- this frame is the
- // caller of a signal handler. The default definition for this
- // handler function simply returns true, allowing parsing of the
- // entry to continue.
- //
- // The best description of the rationale for and meaning of signal
- // trampoline CFI entries seems to be in the GCC bug database:
- // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26208
- virtual bool SignalHandler() { return true; }
-};
-
-// The CallFrameInfo class makes calls on an instance of this class to
-// report errors or warn about problems in the data it is parsing. The
-// default definitions of these methods print a message to stderr, but
-// you can make a derived class that overrides them.
-class CallFrameInfo::Reporter {
- public:
- // Create an error reporter which attributes troubles to the section
- // named SECTION in FILENAME.
- //
- // Normally SECTION would be .debug_frame, but the Mac puts CFI data
- // in a Mach-O section named __debug_frame. If we support
- // Linux-style exception handling data, we could be reading an
- // .eh_frame section.
- Reporter(const string &filename,
- const string &section = ".debug_frame")
- : filename_(filename), section_(section) { }
- virtual ~Reporter() { }
-
- // The CFI entry at OFFSET ends too early to be well-formed. KIND
- // indicates what kind of entry it is; KIND can be kUnknown if we
- // haven't parsed enough of the entry to tell yet.
- virtual void Incomplete(uint64 offset, CallFrameInfo::EntryKind kind);
-
- // The .eh_frame data has a four-byte zero at OFFSET where the next
- // entry's length would be; this is a terminator. However, the buffer
- // length as given to the CallFrameInfo constructor says there should be
- // more data.
- virtual void EarlyEHTerminator(uint64 offset);
-
- // The FDE at OFFSET refers to the CIE at CIE_OFFSET, but the
- // section is not that large.
- virtual void CIEPointerOutOfRange(uint64 offset, uint64 cie_offset);
-
- // The FDE at OFFSET refers to the CIE at CIE_OFFSET, but the entry
- // there is not a CIE.
- virtual void BadCIEId(uint64 offset, uint64 cie_offset);
-
- // The FDE at OFFSET refers to a CIE with version number VERSION,
- // which we don't recognize. We cannot parse DWARF CFI if it uses
- // a version number we don't recognize.
- virtual void UnrecognizedVersion(uint64 offset, int version);
-
- // The FDE at OFFSET refers to a CIE with augmentation AUGMENTATION,
- // which we don't recognize. We cannot parse DWARF CFI if it uses
- // augmentations we don't recognize.
- virtual void UnrecognizedAugmentation(uint64 offset,
- const string &augmentation);
-
- // The pointer encoding ENCODING, specified by the CIE at OFFSET, is not
- // a valid encoding.
- virtual void InvalidPointerEncoding(uint64 offset, uint8 encoding);
-
- // The pointer encoding ENCODING, specified by the CIE at OFFSET, depends
- // on a base address which has not been supplied.
- virtual void UnusablePointerEncoding(uint64 offset, uint8 encoding);
-
- // The CIE at OFFSET contains a DW_CFA_restore instruction at
- // INSN_OFFSET, which may not appear in a CIE.
- virtual void RestoreInCIE(uint64 offset, uint64 insn_offset);
-
- // The entry at OFFSET, of kind KIND, has an unrecognized
- // instruction at INSN_OFFSET.
- virtual void BadInstruction(uint64 offset, CallFrameInfo::EntryKind kind,
- uint64 insn_offset);
-
- // The instruction at INSN_OFFSET in the entry at OFFSET, of kind
- // KIND, establishes a rule that cites the CFA, but we have not
- // established a CFA rule yet.
- virtual void NoCFARule(uint64 offset, CallFrameInfo::EntryKind kind,
- uint64 insn_offset);
-
- // The instruction at INSN_OFFSET in the entry at OFFSET, of kind
- // KIND, is a DW_CFA_restore_state instruction, but the stack of
- // saved states is empty.
- virtual void EmptyStateStack(uint64 offset, CallFrameInfo::EntryKind kind,
- uint64 insn_offset);
-
- // The DW_CFA_remember_state instruction at INSN_OFFSET in the entry
- // at OFFSET, of kind KIND, would restore a state that has no CFA
- // rule, whereas the current state does have a CFA rule. This is
- // bogus input, which the CallFrameInfo::Handler interface doesn't
- // (and shouldn't) have any way to report.
- virtual void ClearingCFARule(uint64 offset, CallFrameInfo::EntryKind kind,
- uint64 insn_offset);
-
- protected:
- // The name of the file whose CFI we're reading.
- string filename_;
-
- // The name of the CFI section in that file.
- string section_;
-};
-
-} // namespace dwarf2reader
-
-#endif // UTIL_DEBUGINFO_DWARF2READER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc
deleted file mode 100644
index e50ea5fbd..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_cfi_unittest.cc
+++ /dev/null
@@ -1,2468 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2reader_cfi_unittest.cc: Unit tests for dwarf2reader::CallFrameInfo
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <string>
-#include <vector>
-
-// The '.eh_frame' format, used by the Linux C++ ABI for exception
-// handling, is poorly specified. To help test our support for .eh_frame,
-// if you #define WRITE_ELF while compiling this file, and add the
-// 'include' directory from the binutils, gcc, or gdb source tree to the
-// #include path, then each test that calls the
-// PERHAPS_WRITE_DEBUG_FRAME_FILE or PERHAPS_WRITE_EH_FRAME_FILE will write
-// an ELF file containing a .debug_frame or .eh_frame section; you can then
-// use tools like readelf to examine the test data, and check the tools'
-// interpretation against the test's intentions. Each ELF file is named
-// "cfitest-TEST", where TEST identifies the particular test.
-#ifdef WRITE_ELF
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-extern "C" {
-// To compile with WRITE_ELF, you should add the 'include' directory
-// of the binutils, gcc, or gdb source tree to your #include path;
-// that directory contains this header.
-#include "elf/common.h"
-}
-#endif
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/cfi_assembler.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-using google_breakpad::CFISection;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Section;
-
-using dwarf2reader::DwarfPointerEncoding;
-using dwarf2reader::ENDIANNESS_BIG;
-using dwarf2reader::ENDIANNESS_LITTLE;
-using dwarf2reader::ByteReader;
-using dwarf2reader::CallFrameInfo;
-
-using std::vector;
-using testing::InSequence;
-using testing::Return;
-using testing::Sequence;
-using testing::Test;
-using testing::_;
-
-#ifdef WRITE_ELF
-void WriteELFFrameSection(const char *filename, const char *section_name,
- const CFISection &section);
-#define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section) \
- WriteELFFrameSection("cfitest-" name, ".debug_frame", section);
-#define PERHAPS_WRITE_EH_FRAME_FILE(name, section) \
- WriteELFFrameSection("cfitest-" name, ".eh_frame", section);
-#else
-#define PERHAPS_WRITE_DEBUG_FRAME_FILE(name, section)
-#define PERHAPS_WRITE_EH_FRAME_FILE(name, section)
-#endif
-
-class MockCallFrameInfoHandler: public CallFrameInfo::Handler {
- public:
- MOCK_METHOD6(Entry, bool(size_t offset, uint64 address, uint64 length,
- uint8 version, const string &augmentation,
- unsigned return_address));
- MOCK_METHOD2(UndefinedRule, bool(uint64 address, int reg));
- MOCK_METHOD2(SameValueRule, bool(uint64 address, int reg));
- MOCK_METHOD4(OffsetRule, bool(uint64 address, int reg, int base_register,
- long offset));
- MOCK_METHOD4(ValOffsetRule, bool(uint64 address, int reg, int base_register,
- long offset));
- MOCK_METHOD3(RegisterRule, bool(uint64 address, int reg, int base_register));
- MOCK_METHOD3(ExpressionRule, bool(uint64 address, int reg,
- const string &expression));
- MOCK_METHOD3(ValExpressionRule, bool(uint64 address, int reg,
- const string &expression));
- MOCK_METHOD0(End, bool());
- MOCK_METHOD2(PersonalityRoutine, bool(uint64 address, bool indirect));
- MOCK_METHOD2(LanguageSpecificDataArea, bool(uint64 address, bool indirect));
- MOCK_METHOD0(SignalHandler, bool());
-};
-
-class MockCallFrameErrorReporter: public CallFrameInfo::Reporter {
- public:
- MockCallFrameErrorReporter() : Reporter("mock filename", "mock section") { }
- MOCK_METHOD2(Incomplete, void(uint64, CallFrameInfo::EntryKind));
- MOCK_METHOD1(EarlyEHTerminator, void(uint64));
- MOCK_METHOD2(CIEPointerOutOfRange, void(uint64, uint64));
- MOCK_METHOD2(BadCIEId, void(uint64, uint64));
- MOCK_METHOD2(UnrecognizedVersion, void(uint64, int version));
- MOCK_METHOD2(UnrecognizedAugmentation, void(uint64, const string &));
- MOCK_METHOD2(InvalidPointerEncoding, void(uint64, uint8));
- MOCK_METHOD2(UnusablePointerEncoding, void(uint64, uint8));
- MOCK_METHOD2(RestoreInCIE, void(uint64, uint64));
- MOCK_METHOD3(BadInstruction, void(uint64, CallFrameInfo::EntryKind, uint64));
- MOCK_METHOD3(NoCFARule, void(uint64, CallFrameInfo::EntryKind, uint64));
- MOCK_METHOD3(EmptyStateStack, void(uint64, CallFrameInfo::EntryKind, uint64));
-};
-
-struct CFIFixture {
-
- enum { kCFARegister = CallFrameInfo::Handler::kCFARegister };
-
- CFIFixture() {
- // Default expectations for the data handler.
- //
- // - Leave Entry and End without expectations, as it's probably a
- // good idea to set those explicitly in each test.
- //
- // - Expect the *Rule functions to not be called,
- // so that each test can simply list the calls they expect.
- //
- // I gather I could use StrictMock for this, but the manual seems
- // to suggest using that only as a last resort, and this isn't so
- // bad.
- EXPECT_CALL(handler, UndefinedRule(_, _)).Times(0);
- EXPECT_CALL(handler, SameValueRule(_, _)).Times(0);
- EXPECT_CALL(handler, OffsetRule(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, ValOffsetRule(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, RegisterRule(_, _, _)).Times(0);
- EXPECT_CALL(handler, ExpressionRule(_, _, _)).Times(0);
- EXPECT_CALL(handler, ValExpressionRule(_, _, _)).Times(0);
- EXPECT_CALL(handler, PersonalityRoutine(_, _)).Times(0);
- EXPECT_CALL(handler, LanguageSpecificDataArea(_, _)).Times(0);
- EXPECT_CALL(handler, SignalHandler()).Times(0);
-
- // Default expectations for the error/warning reporer.
- EXPECT_CALL(reporter, Incomplete(_, _)).Times(0);
- EXPECT_CALL(reporter, EarlyEHTerminator(_)).Times(0);
- EXPECT_CALL(reporter, CIEPointerOutOfRange(_, _)).Times(0);
- EXPECT_CALL(reporter, BadCIEId(_, _)).Times(0);
- EXPECT_CALL(reporter, UnrecognizedVersion(_, _)).Times(0);
- EXPECT_CALL(reporter, UnrecognizedAugmentation(_, _)).Times(0);
- EXPECT_CALL(reporter, InvalidPointerEncoding(_, _)).Times(0);
- EXPECT_CALL(reporter, UnusablePointerEncoding(_, _)).Times(0);
- EXPECT_CALL(reporter, RestoreInCIE(_, _)).Times(0);
- EXPECT_CALL(reporter, BadInstruction(_, _, _)).Times(0);
- EXPECT_CALL(reporter, NoCFARule(_, _, _)).Times(0);
- EXPECT_CALL(reporter, EmptyStateStack(_, _, _)).Times(0);
- }
-
- MockCallFrameInfoHandler handler;
- MockCallFrameErrorReporter reporter;
-};
-
-class CFI: public CFIFixture, public Test { };
-
-TEST_F(CFI, EmptyRegion) {
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
- static const uint8_t data[] = { 42 };
-
- ByteReader byte_reader(ENDIANNESS_BIG);
- CallFrameInfo parser(data, 0, &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-TEST_F(CFI, IncompleteLength32) {
- CFISection section(kBigEndian, 8);
- section
- // Not even long enough for an initial length.
- .D16(0xa0f)
- // Padding to keep valgrind happy. We subtract these off when we
- // construct the parser.
- .D16(0);
-
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
-
- EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
- .WillOnce(Return());
-
- string contents;
- ASSERT_TRUE(section.GetContents(&contents));
-
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size() - 2,
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-TEST_F(CFI, IncompleteLength64) {
- CFISection section(kLittleEndian, 4);
- section
- // An incomplete 64-bit DWARF initial length.
- .D32(0xffffffff).D32(0x71fbaec2)
- // Padding to keep valgrind happy. We subtract these off when we
- // construct the parser.
- .D32(0);
-
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
-
- EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
- .WillOnce(Return());
-
- string contents;
- ASSERT_TRUE(section.GetContents(&contents));
-
- ByteReader byte_reader(ENDIANNESS_LITTLE);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size() - 4,
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-TEST_F(CFI, IncompleteId32) {
- CFISection section(kBigEndian, 8);
- section
- .D32(3) // Initial length, not long enough for id
- .D8(0xd7).D8(0xe5).D8(0xf1) // incomplete id
- .CIEHeader(8727, 3983, 8889, 3, "")
- .FinishEntry();
-
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
-
- EXPECT_CALL(reporter, Incomplete(_, CallFrameInfo::kUnknown))
- .WillOnce(Return());
-
- string contents;
- ASSERT_TRUE(section.GetContents(&contents));
-
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-TEST_F(CFI, BadId32) {
- CFISection section(kBigEndian, 8);
- section
- .D32(0x100) // Initial length
- .D32(0xe802fade) // bogus ID
- .Append(0x100 - 4, 0x42); // make the length true
- section
- .CIEHeader(1672, 9872, 8529, 3, "")
- .FinishEntry();
-
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
-
- EXPECT_CALL(reporter, CIEPointerOutOfRange(_, 0xe802fade))
- .WillOnce(Return());
-
- string contents;
- ASSERT_TRUE(section.GetContents(&contents));
-
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-// A lone CIE shouldn't cause any handler calls.
-TEST_F(CFI, SingleCIE) {
- CFISection section(kLittleEndian, 4);
- section.CIEHeader(0xffe799a8, 0x3398dcdd, 0x6e9683de, 3, "");
- section.Append(10, dwarf2reader::DW_CFA_nop);
- section.FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("SingleCIE", section);
-
- EXPECT_CALL(handler, Entry(_, _, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, End()).Times(0);
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_LITTLE);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-// One FDE, one CIE.
-TEST_F(CFI, OneFDE) {
- CFISection section(kBigEndian, 4);
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "")
- .FinishEntry()
- .FDEHeader(cie, 0x7714740d, 0x3d5a10cd)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("OneFDE", section);
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, 0x7714740d, 0x3d5a10cd, 3, "", 0x6b6efb87))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-// Two FDEs share a CIE.
-TEST_F(CFI, TwoFDEsOneCIE) {
- CFISection section(kBigEndian, 4);
- Label cie;
- section
- // First FDE. readelf complains about this one because it makes
- // a forward reference to its CIE.
- .FDEHeader(cie, 0xa42744df, 0xa3b42121)
- .FinishEntry()
- // CIE.
- .Mark(&cie)
- .CIEHeader(0x04f7dc7b, 0x3d00c05f, 0xbd43cb59, 3, "")
- .FinishEntry()
- // Second FDE.
- .FDEHeader(cie, 0x6057d391, 0x700f608d)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsOneCIE", section);
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, 0xa42744df, 0xa3b42121, 3, "", 0xbd43cb59))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, 0x6057d391, 0x700f608d, 3, "", 0xbd43cb59))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-// Two FDEs, two CIEs.
-TEST_F(CFI, TwoFDEsTwoCIEs) {
- CFISection section(kLittleEndian, 8);
- Label cie1, cie2;
- section
- // First CIE.
- .Mark(&cie1)
- .CIEHeader(0x694d5d45, 0x4233221b, 0xbf45e65a, 3, "")
- .FinishEntry()
- // First FDE which cites second CIE. readelf complains about
- // this one because it makes a forward reference to its CIE.
- .FDEHeader(cie2, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL)
- .FinishEntry()
- // Second FDE, which cites first CIE.
- .FDEHeader(cie1, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL)
- .FinishEntry()
- // Second CIE.
- .Mark(&cie2)
- .CIEHeader(0xfba3fad7, 0x6287e1fd, 0x61d2c581, 2, "")
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("TwoFDEsTwoCIEs", section);
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, 0x778b27dfe5871f05ULL, 0x324ace3448070926ULL, 2,
- "", 0x61d2c581))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, 0xf6054ca18b10bf5fULL, 0x45fdb970d8bca342ULL, 3,
- "", 0xbf45e65a))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_LITTLE);
- byte_reader.SetAddressSize(8);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-// An FDE whose CIE specifies a version we don't recognize.
-TEST_F(CFI, BadVersion) {
- CFISection section(kBigEndian, 4);
- Label cie1, cie2;
- section
- .Mark(&cie1)
- .CIEHeader(0xca878cf0, 0x7698ec04, 0x7b616f54, 0x52, "")
- .FinishEntry()
- // We should skip this entry, as its CIE specifies a version we
- // don't recognize.
- .FDEHeader(cie1, 0x08852292, 0x2204004a)
- .FinishEntry()
- // Despite the above, we should visit this entry.
- .Mark(&cie2)
- .CIEHeader(0x7c3ae7c9, 0xb9b9a512, 0x96cb3264, 3, "")
- .FinishEntry()
- .FDEHeader(cie2, 0x2094735a, 0x6e875501)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("BadVersion", section);
-
- EXPECT_CALL(reporter, UnrecognizedVersion(_, 0x52))
- .WillOnce(Return());
-
- {
- InSequence s;
- // We should see no mention of the first FDE, but we should get
- // a call to Entry for the second.
- EXPECT_CALL(handler, Entry(_, 0x2094735a, 0x6e875501, 3, "",
- 0x96cb3264))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-// An FDE whose CIE specifies an augmentation we don't recognize.
-TEST_F(CFI, BadAugmentation) {
- CFISection section(kBigEndian, 4);
- Label cie1, cie2;
- section
- .Mark(&cie1)
- .CIEHeader(0x4be22f75, 0x2492236e, 0x6b6efb87, 3, "spaniels!")
- .FinishEntry()
- // We should skip this entry, as its CIE specifies an
- // augmentation we don't recognize.
- .FDEHeader(cie1, 0x7714740d, 0x3d5a10cd)
- .FinishEntry()
- // Despite the above, we should visit this entry.
- .Mark(&cie2)
- .CIEHeader(0xf8bc4399, 0x8cf09931, 0xf2f519b2, 3, "")
- .FinishEntry()
- .FDEHeader(cie2, 0x7bf0fda0, 0xcbcd28d8)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("BadAugmentation", section);
-
- EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "spaniels!"))
- .WillOnce(Return());
-
- {
- InSequence s;
- // We should see no mention of the first FDE, but we should get
- // a call to Entry for the second.
- EXPECT_CALL(handler, Entry(_, 0x7bf0fda0, 0xcbcd28d8, 3, "",
- 0xf2f519b2))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_FALSE(parser.Start());
-}
-
-// The return address column field is a byte in CFI version 1
-// (DWARF2), but a ULEB128 value in version 3 (DWARF3).
-TEST_F(CFI, CIEVersion1ReturnColumn) {
- CFISection section(kBigEndian, 4);
- Label cie;
- section
- // CIE, using the version 1 format: return column is a ubyte.
- .Mark(&cie)
- // Use a value for the return column that is parsed differently
- // as a ubyte and as a ULEB128.
- .CIEHeader(0xbcdea24f, 0x5be28286, 0x9f, 1, "")
- .FinishEntry()
- // FDE, citing that CIE.
- .FDEHeader(cie, 0xb8d347b5, 0x825e55dc)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion1ReturnColumn", section);
-
- {
- InSequence s;
- EXPECT_CALL(handler, Entry(_, 0xb8d347b5, 0x825e55dc, 1, "", 0x9f))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-// The return address column field is a byte in CFI version 1
-// (DWARF2), but a ULEB128 value in version 3 (DWARF3).
-TEST_F(CFI, CIEVersion3ReturnColumn) {
- CFISection section(kBigEndian, 4);
- Label cie;
- section
- // CIE, using the version 3 format: return column is a ULEB128.
- .Mark(&cie)
- // Use a value for the return column that is parsed differently
- // as a ubyte and as a ULEB128.
- .CIEHeader(0x0ab4758d, 0xc010fdf7, 0x89, 3, "")
- .FinishEntry()
- // FDE, citing that CIE.
- .FDEHeader(cie, 0x86763f2b, 0x2a66dc23)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("CIEVersion3ReturnColumn", section);
-
- {
- InSequence s;
- EXPECT_CALL(handler, Entry(_, 0x86763f2b, 0x2a66dc23, 3, "", 0x89))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- string contents;
- EXPECT_TRUE(section.GetContents(&contents));
- ByteReader byte_reader(ENDIANNESS_BIG);
- byte_reader.SetAddressSize(4);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- EXPECT_TRUE(parser.Start());
-}
-
-struct CFIInsnFixture: public CFIFixture {
- CFIInsnFixture() : CFIFixture() {
- data_factor = 0xb6f;
- return_register = 0x9be1ed9f;
- version = 3;
- cfa_base_register = 0x383a3aa;
- cfa_offset = 0xf748;
- }
-
- // Prepare SECTION to receive FDE instructions.
- //
- // - Append a stock CIE header that establishes the fixture's
- // code_factor, data_factor, return_register, version, and
- // augmentation values.
- // - Have the CIE set up a CFA rule using cfa_base_register and
- // cfa_offset.
- // - Append a stock FDE header, referring to the above CIE, for the
- // fde_size bytes at fde_start. Choose fde_start and fde_size
- // appropriately for the section's address size.
- // - Set appropriate expectations on handler in sequence s for the
- // frame description entry and the CIE's CFA rule.
- //
- // On return, SECTION is ready to have FDE instructions appended to
- // it, and its FinishEntry member called.
- void StockCIEAndFDE(CFISection *section) {
- // Choose appropriate constants for our address size.
- if (section->AddressSize() == 4) {
- fde_start = 0xc628ecfbU;
- fde_size = 0x5dee04a2;
- code_factor = 0x60b;
- } else {
- assert(section->AddressSize() == 8);
- fde_start = 0x0005c57ce7806bd3ULL;
- fde_size = 0x2699521b5e333100ULL;
- code_factor = 0x01008e32855274a8ULL;
- }
-
- // Create the CIE.
- (*section)
- .Mark(&cie_label)
- .CIEHeader(code_factor, data_factor, return_register, version,
- "")
- .D8(dwarf2reader::DW_CFA_def_cfa)
- .ULEB128(cfa_base_register)
- .ULEB128(cfa_offset)
- .FinishEntry();
-
- // Create the FDE.
- section->FDEHeader(cie_label, fde_start, fde_size);
-
- // Expect an Entry call for the FDE and a ValOffsetRule call for the
- // CIE's CFA rule.
- EXPECT_CALL(handler, Entry(_, fde_start, fde_size, version, "",
- return_register))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(fde_start, kCFARegister,
- cfa_base_register, cfa_offset))
- .InSequence(s)
- .WillOnce(Return(true));
- }
-
- // Run the contents of SECTION through a CallFrameInfo parser,
- // expecting parser.Start to return SUCCEEDS
- void ParseSection(CFISection *section, bool succeeds = true) {
- string contents;
- EXPECT_TRUE(section->GetContents(&contents));
- dwarf2reader::Endianness endianness;
- if (section->endianness() == kBigEndian)
- endianness = ENDIANNESS_BIG;
- else {
- assert(section->endianness() == kLittleEndian);
- endianness = ENDIANNESS_LITTLE;
- }
- ByteReader byte_reader(endianness);
- byte_reader.SetAddressSize(section->AddressSize());
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter);
- if (succeeds)
- EXPECT_TRUE(parser.Start());
- else
- EXPECT_FALSE(parser.Start());
- }
-
- Label cie_label;
- Sequence s;
- uint64 code_factor;
- int data_factor;
- unsigned return_register;
- unsigned version;
- unsigned cfa_base_register;
- int cfa_offset;
- uint64 fde_start, fde_size;
-};
-
-class CFIInsn: public CFIInsnFixture, public Test { };
-
-TEST_F(CFIInsn, DW_CFA_set_loc) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_set_loc).D32(0xb1ee3e7a)
- // Use DW_CFA_def_cfa to force a handler call that we can use to
- // check the effect of the DW_CFA_set_loc.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4defb431).ULEB128(0x6d17b0ee)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_set_loc", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule(0xb1ee3e7a, kCFARegister, 0x4defb431, 0x6d17b0ee))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_advance_loc) {
- CFISection section(kBigEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x2a)
- // Use DW_CFA_def_cfa to force a handler call that we can use to
- // check the effect of the DW_CFA_advance_loc.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x5bbb3715).ULEB128(0x0186c7bf)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start + 0x2a * code_factor,
- kCFARegister, 0x5bbb3715, 0x0186c7bf))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_advance_loc1) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_advance_loc1).D8(0xd8)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x69d5696a).ULEB128(0x1eb7fc93)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc1", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule((fde_start + 0xd8 * code_factor),
- kCFARegister, 0x69d5696a, 0x1eb7fc93))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_advance_loc2) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_advance_loc2).D16(0x3adb)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3a368bed).ULEB128(0x3194ee37)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc2", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule((fde_start + 0x3adb * code_factor),
- kCFARegister, 0x3a368bed, 0x3194ee37))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_advance_loc4) {
- CFISection section(kBigEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_advance_loc4).D32(0x15813c88)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x135270c5).ULEB128(0x24bad7cb)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc4", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule((fde_start + 0x15813c88ULL * code_factor),
- kCFARegister, 0x135270c5, 0x24bad7cb))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_MIPS_advance_loc8) {
- code_factor = 0x2d;
- CFISection section(kBigEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_MIPS_advance_loc8).D64(0x3c4f3945b92c14ULL)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0xe17ed602).ULEB128(0x3d162e7f)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_advance_loc8", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule((fde_start + 0x3c4f3945b92c14ULL * code_factor),
- kCFARegister, 0xe17ed602, 0x3d162e7f))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x4e363a85).ULEB128(0x815f9aa7)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("DW_CFA_def_cfa", section);
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x4e363a85, 0x815f9aa7))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa_sf) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x8ccb32b7).LEB128(0x9ea)
- .D8(dwarf2reader::DW_CFA_def_cfa_sf).ULEB128(0x9b40f5da).LEB128(-0x40a2)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x8ccb32b7,
- 0x9ea * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x9b40f5da,
- -0x40a2 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa_register) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0x3e7e9363)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x3e7e9363, cfa_offset))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-// DW_CFA_def_cfa_register should have no effect when applied to a
-// non-base/offset rule.
-TEST_F(CFIInsn, DW_CFA_def_cfa_registerBadRule) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("needle in a haystack")
- .D8(dwarf2reader::DW_CFA_def_cfa_register).ULEB128(0xf1b49e49)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValExpressionRule(fde_start, kCFARegister,
- "needle in a haystack"))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa_offset) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
- 0x1e8e3b9b))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa_offset_sf) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(0x970)
- .D8(dwarf2reader::DW_CFA_def_cfa_offset_sf).LEB128(-0x2cd)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
- 0x970 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, cfa_base_register,
- -0x2cd * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-// DW_CFA_def_cfa_offset should have no effect when applied to a
-// non-base/offset rule.
-TEST_F(CFIInsn, DW_CFA_def_cfa_offsetBadRule) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("six ways to Sunday")
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x1e8e3b9b)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValExpressionRule(fde_start, kCFARegister, "six ways to Sunday"))
- .WillRepeatedly(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_def_cfa_expression) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_def_cfa_expression).Block("eating crow")
- .FinishEntry();
-
- EXPECT_CALL(handler, ValExpressionRule(fde_start, kCFARegister,
- "eating crow"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_undefined) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x300ce45d)
- .FinishEntry();
-
- EXPECT_CALL(handler, UndefinedRule(fde_start, 0x300ce45d))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_same_value) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3865a760)
- .FinishEntry();
-
- EXPECT_CALL(handler, SameValueRule(fde_start, 0x3865a760))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_offset) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x9f6)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x2c, kCFARegister, 0x9f6 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_offset_extended) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset_extended).ULEB128(0x402b).ULEB128(0xb48)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x402b, kCFARegister, 0xb48 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_offset_extended_sf) {
- CFISection section(kBigEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset_extended_sf)
- .ULEB128(0x997c23ee).LEB128(0x2d00)
- .D8(dwarf2reader::DW_CFA_offset_extended_sf)
- .ULEB128(0x9519eb82).LEB128(-0xa77)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x997c23ee,
- kCFARegister, 0x2d00 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x9519eb82,
- kCFARegister, -0xa77 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_val_offset) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x623562fe).ULEB128(0x673)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, 0x623562fe,
- kCFARegister, 0x673 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_val_offset_sf) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x6f4f).LEB128(0xaab)
- .D8(dwarf2reader::DW_CFA_val_offset_sf).ULEB128(0x2483).LEB128(-0x8a2)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, 0x6f4f,
- kCFARegister, 0xaab * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, 0x2483,
- kCFARegister, -0x8a2 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_register) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x278d18f9).ULEB128(0x1a684414)
- .FinishEntry();
-
- EXPECT_CALL(handler, RegisterRule(fde_start, 0x278d18f9, 0x1a684414))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_expression) {
- CFISection section(kBigEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xa1619fb2)
- .Block("plus ça change, plus c'est la même chose")
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ExpressionRule(fde_start, 0xa1619fb2,
- "plus ça change, plus c'est la même chose"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_val_expression) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xc5e4a9e3)
- .Block("he who has the gold makes the rules")
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValExpressionRule(fde_start, 0xc5e4a9e3,
- "he who has the gold makes the rules"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_restore) {
- CFISection section(kLittleEndian, 8);
- code_factor = 0x01bd188a9b1fa083ULL;
- data_factor = -0x1ac8;
- return_register = 0x8c35b049;
- version = 2;
- fde_start = 0x2d70fe998298bbb1ULL;
- fde_size = 0x46ccc2e63cf0b108ULL;
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(code_factor, data_factor, return_register, version,
- "")
- // Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x6ca1d50e).ULEB128(0x372e38e8)
- // Provide an offset(N) rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0xb348)
- .FinishEntry()
- // In the FDE...
- .FDEHeader(cie, fde_start, fde_size)
- // At a second address, provide a new offset(N) rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x13)
- .D8(dwarf2reader::DW_CFA_offset | 0x3c).ULEB128(0x9a50)
- // At a third address, restore the original rule for register 0x3c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x01)
- .D8(dwarf2reader::DW_CFA_restore | 0x3c)
- .FinishEntry();
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, fde_start, fde_size, version, "", return_register))
- .WillOnce(Return(true));
- // CIE's CFA rule.
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x6ca1d50e, 0x372e38e8))
- .WillOnce(Return(true));
- // CIE's rule for register 0x3c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x3c, kCFARegister, 0xb348 * data_factor))
- .WillOnce(Return(true));
- // FDE's rule for register 0x3c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start + 0x13 * code_factor, 0x3c,
- kCFARegister, 0x9a50 * data_factor))
- .WillOnce(Return(true));
- // Restore CIE's rule for register 0x3c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start + (0x13 + 0x01) * code_factor, 0x3c,
- kCFARegister, 0xb348 * data_factor))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_restoreNoRule) {
- CFISection section(kBigEndian, 4);
- code_factor = 0x005f78143c1c3b82ULL;
- data_factor = 0x25d0;
- return_register = 0xe8;
- version = 1;
- fde_start = 0x4062e30f;
- fde_size = 0x5302a389;
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(code_factor, data_factor, return_register, version, "")
- // Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x470aa334).ULEB128(0x099ef127)
- .FinishEntry()
- // In the FDE...
- .FDEHeader(cie, fde_start, fde_size)
- // At a second address, provide an offset(N) rule for register 0x2c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x7)
- .D8(dwarf2reader::DW_CFA_offset | 0x2c).ULEB128(0x1f47)
- // At a third address, restore the (missing) CIE rule for register 0x2c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0xb)
- .D8(dwarf2reader::DW_CFA_restore | 0x2c)
- .FinishEntry();
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, fde_start, fde_size, version, "", return_register))
- .WillOnce(Return(true));
- // CIE's CFA rule.
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x470aa334, 0x099ef127))
- .WillOnce(Return(true));
- // FDE's rule for register 0x2c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start + 0x7 * code_factor, 0x2c,
- kCFARegister, 0x1f47 * data_factor))
- .WillOnce(Return(true));
- // Restore CIE's (missing) rule for register 0x2c.
- EXPECT_CALL(handler,
- SameValueRule(fde_start + (0x7 + 0xb) * code_factor, 0x2c))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_restore_extended) {
- CFISection section(kBigEndian, 4);
- code_factor = 0x126e;
- data_factor = -0xd8b;
- return_register = 0x77711787;
- version = 3;
- fde_start = 0x01f55a45;
- fde_size = 0x452adb80;
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(code_factor, data_factor, return_register, version,
- "", true /* dwarf64 */ )
- // Provide a CFA rule, because register rules require them.
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x56fa0edd).ULEB128(0x097f78a5)
- // Provide an offset(N) rule for register 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_offset_extended)
- .ULEB128(0x0f9b8a1c).ULEB128(0xc979)
- .FinishEntry()
- // In the FDE...
- .FDEHeader(cie, fde_start, fde_size)
- // At a second address, provide a new offset(N) rule for reg 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x3)
- .D8(dwarf2reader::DW_CFA_offset_extended)
- .ULEB128(0x0f9b8a1c).ULEB128(0x3b7b)
- // At a third address, restore the original rule for register 0x0f9b8a1c.
- .D8(dwarf2reader::DW_CFA_advance_loc | 0x04)
- .D8(dwarf2reader::DW_CFA_restore_extended).ULEB128(0x0f9b8a1c)
- .FinishEntry();
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- Entry(_, fde_start, fde_size, version, "", return_register))
- .WillOnce(Return(true));
- // CIE's CFA rule.
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x56fa0edd, 0x097f78a5))
- .WillOnce(Return(true));
- // CIE's rule for register 0x0f9b8a1c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x0f9b8a1c, kCFARegister,
- 0xc979 * data_factor))
- .WillOnce(Return(true));
- // FDE's rule for register 0x0f9b8a1c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start + 0x3 * code_factor, 0x0f9b8a1c,
- kCFARegister, 0x3b7b * data_factor))
- .WillOnce(Return(true));
- // Restore CIE's rule for register 0x0f9b8a1c.
- EXPECT_CALL(handler,
- OffsetRule(fde_start + (0x3 + 0x4) * code_factor, 0x0f9b8a1c,
- kCFARegister, 0xc979 * data_factor))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
- }
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_remember_and_restore_state) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
-
- // We create a state, save it, modify it, and then restore. We
- // refer to the state that is overridden the restore as the
- // "outgoing" state, and the restored state the "incoming" state.
- //
- // Register outgoing incoming expect
- // 1 offset(N) no rule new "same value" rule
- // 2 register(R) offset(N) report changed rule
- // 3 offset(N) offset(M) report changed offset
- // 4 offset(N) offset(N) no report
- // 5 offset(N) no rule new "same value" rule
- section
- // Create the "incoming" state, which we will save and later restore.
- .D8(dwarf2reader::DW_CFA_offset | 2).ULEB128(0x9806)
- .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0x995d)
- .D8(dwarf2reader::DW_CFA_offset | 4).ULEB128(0x7055)
- .D8(dwarf2reader::DW_CFA_remember_state)
- // Advance to a new instruction; an implementation could legitimately
- // ignore all but the final rule for a given register at a given address.
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- // Create the "outgoing" state, which we will discard.
- .D8(dwarf2reader::DW_CFA_offset | 1).ULEB128(0xea1a)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(2).ULEB128(0x1d2a3767)
- .D8(dwarf2reader::DW_CFA_offset | 3).ULEB128(0xdd29)
- .D8(dwarf2reader::DW_CFA_offset | 5).ULEB128(0xf1ce)
- // At a third address, restore the incoming state.
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- uint64 addr = fde_start;
-
- // Expect the incoming rules to be reported.
- EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 4, kCFARegister, 0x7055 * data_factor))
- .InSequence(s).WillOnce(Return(true));
-
- addr += code_factor;
-
- // After the save, we establish the outgoing rule set.
- EXPECT_CALL(handler, OffsetRule(addr, 1, kCFARegister, 0xea1a * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(addr, 2, 0x1d2a3767))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0xdd29 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 5, kCFARegister, 0xf1ce * data_factor))
- .InSequence(s).WillOnce(Return(true));
-
- addr += code_factor;
-
- // Finally, after the restore, expect to see the differences from
- // the outgoing to the incoming rules reported.
- EXPECT_CALL(handler, SameValueRule(addr, 1))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 2, kCFARegister, 0x9806 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(addr, 3, kCFARegister, 0x995d * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, SameValueRule(addr, 5))
- .InSequence(s).WillOnce(Return(true));
-
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-// Check that restoring a rule set reports changes to the CFA rule.
-TEST_F(CFIInsn, DW_CFA_remember_and_restore_stateCFA) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
-
- section
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_def_cfa_offset).ULEB128(0x90481102)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, kCFARegister,
- cfa_base_register, 0x90481102))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor * 2, kCFARegister,
- cfa_base_register, cfa_offset))
- .InSequence(s).WillOnce(Return(true));
-
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_nop) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_nop)
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x3fb8d4f1).ULEB128(0x078dc67b)
- .D8(dwarf2reader::DW_CFA_nop)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- ValOffsetRule(fde_start, kCFARegister, 0x3fb8d4f1, 0x078dc67b))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_GNU_window_save) {
- CFISection section(kBigEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_GNU_window_save)
- .FinishEntry();
-
- // Don't include all the rules in any particular sequence.
-
- // The caller's %o0-%o7 have become the callee's %i0-%i7. This is
- // the GCC register numbering.
- for (int i = 8; i < 16; i++)
- EXPECT_CALL(handler, RegisterRule(fde_start, i, i + 16))
- .WillOnce(Return(true));
- // The caller's %l0-%l7 and %i0-%i7 have been saved at the top of
- // its frame.
- for (int i = 16; i < 32; i++)
- EXPECT_CALL(handler, OffsetRule(fde_start, i, kCFARegister, (i-16) * 4))
- .WillOnce(Return(true));
-
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_GNU_args_size) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_GNU_args_size).ULEB128(0xeddfa520)
- // Verify that we see this, meaning we parsed the above properly.
- .D8(dwarf2reader::DW_CFA_offset | 0x23).ULEB128(0x269)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x23, kCFARegister, 0x269 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIInsn, DW_CFA_GNU_negative_offset_extended) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_GNU_negative_offset_extended)
- .ULEB128(0x430cc87a).ULEB128(0x613)
- .FinishEntry();
-
- EXPECT_CALL(handler,
- OffsetRule(fde_start, 0x430cc87a,
- kCFARegister, -0x613 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-// Three FDEs: skip the second
-TEST_F(CFIInsn, SkipFDE) {
- CFISection section(kBigEndian, 4);
- Label cie;
- section
- // CIE, used by all FDEs.
- .Mark(&cie)
- .CIEHeader(0x010269f2, 0x9177, 0xedca5849, 2, "")
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(0x42ed390b).ULEB128(0x98f43aad)
- .FinishEntry()
- // First FDE.
- .FDEHeader(cie, 0xa870ebdd, 0x60f6aa4)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x3a860351).ULEB128(0x6c9a6bcf)
- .FinishEntry()
- // Second FDE.
- .FDEHeader(cie, 0xc534f7c0, 0xf6552e9, true /* dwarf64 */)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x1b62c234).ULEB128(0x26586b18)
- .FinishEntry()
- // Third FDE.
- .FDEHeader(cie, 0xf681cfc8, 0x7e4594e)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x26c53934).ULEB128(0x18eeb8a4)
- .FinishEntry();
-
- {
- InSequence s;
-
- // Process the first FDE.
- EXPECT_CALL(handler, Entry(_, 0xa870ebdd, 0x60f6aa4, 2, "", 0xedca5849))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(0xa870ebdd, kCFARegister,
- 0x42ed390b, 0x98f43aad))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(0xa870ebdd, 0x3a860351, 0x6c9a6bcf))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .WillOnce(Return(true));
-
- // Skip the second FDE.
- EXPECT_CALL(handler, Entry(_, 0xc534f7c0, 0xf6552e9, 2, "", 0xedca5849))
- .WillOnce(Return(false));
-
- // Process the third FDE.
- EXPECT_CALL(handler, Entry(_, 0xf681cfc8, 0x7e4594e, 2, "", 0xedca5849))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(0xf681cfc8, kCFARegister,
- 0x42ed390b, 0x98f43aad))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(0xf681cfc8, 0x26c53934, 0x18eeb8a4))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .WillOnce(Return(true));
- }
-
- ParseSection(&section);
-}
-
-// Quit processing in the middle of an entry's instructions.
-TEST_F(CFIInsn, QuitMidentry) {
- CFISection section(kLittleEndian, 8);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe0cf850d).ULEB128(0x15aab431)
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x46750aa5).Block("meat")
- .FinishEntry();
-
- EXPECT_CALL(handler, RegisterRule(fde_start, 0xe0cf850d, 0x15aab431))
- .InSequence(s).WillOnce(Return(false));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseSection(&section, false);
-}
-
-class CFIRestore: public CFIInsnFixture, public Test { };
-
-TEST_F(CFIRestore, RestoreUndefinedRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x0bac878e)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, UndefinedRule(fde_start, 0x0bac878e))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreUndefinedRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x7dedff5f)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x7dedff5f)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, UndefinedRule(fde_start, 0x7dedff5f))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, SameValueRule(fde_start + code_factor, 0x7dedff5f))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + 2 * code_factor, 0x7dedff5f))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreSameValueRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0xadbc9b3a)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, SameValueRule(fde_start, 0xadbc9b3a))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreSameValueRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_same_value).ULEB128(0x3d90dcb5)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x3d90dcb5)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, SameValueRule(fde_start, 0x3d90dcb5))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x3d90dcb5))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, SameValueRule(fde_start + 2 * code_factor, 0x3d90dcb5))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreOffsetRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset | 0x14).ULEB128(0xb6f)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, OffsetRule(fde_start, 0x14,
- kCFARegister, 0xb6f * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreOffsetRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xeb7)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x21)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
- kCFARegister, 0xeb7 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0x21))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
- kCFARegister, 0xeb7 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreOffsetRuleChangedOffset) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0x134)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_offset | 0x21).ULEB128(0xf4f)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, OffsetRule(fde_start, 0x21,
- kCFARegister, 0x134 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(fde_start + code_factor, 0x21,
- kCFARegister, 0xf4f * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, OffsetRule(fde_start + 2 * code_factor, 0x21,
- kCFARegister, 0x134 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValOffsetRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x829caee6).ULEB128(0xe4c)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x829caee6,
- kCFARegister, 0xe4c * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValOffsetRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0xf17c36d6).ULEB128(0xeb7)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xf17c36d6)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ValOffsetRule(fde_start, 0xf17c36d6,
- kCFARegister, 0xeb7 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xf17c36d6))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0xf17c36d6,
- kCFARegister, 0xeb7 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValOffsetRuleChangedValOffset) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0x562)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_val_offset).ULEB128(0x2cf0ab1b).ULEB128(0xe88)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ValOffsetRule(fde_start, 0x2cf0ab1b,
- kCFARegister, 0x562 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(fde_start + code_factor, 0x2cf0ab1b,
- kCFARegister, 0xe88 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(fde_start + 2 * code_factor, 0x2cf0ab1b,
- kCFARegister, 0x562 * data_factor))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreRegisterRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0x77514acc).ULEB128(0x464de4ce)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, RegisterRule(fde_start, 0x77514acc, 0x464de4ce))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreRegisterRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xe39acce5).ULEB128(0x095f1559)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xe39acce5)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, RegisterRule(fde_start, 0xe39acce5, 0x095f1559))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xe39acce5))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xe39acce5,
- 0x095f1559))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreRegisterRuleChangedRegister) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0x16607d6a)
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(0xd40e21b1).ULEB128(0xbabb4742)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, RegisterRule(fde_start, 0xd40e21b1, 0x16607d6a))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(fde_start + code_factor, 0xd40e21b1,
- 0xbabb4742))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, RegisterRule(fde_start + 2 * code_factor, 0xd40e21b1,
- 0x16607d6a))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreExpressionRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x666ae152).Block("dwarf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ExpressionRule(fde_start, 0x666ae152, "dwarf"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreExpressionRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0xb5ca5c46).Block("elf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ExpressionRule(fde_start, 0xb5ca5c46, "elf"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
- "elf"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreExpressionRuleChangedExpression) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("smurf")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_expression).ULEB128(0x500f5739).Block("orc")
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ExpressionRule(fde_start, 0x500f5739, "smurf"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ExpressionRule(fde_start + code_factor, 0x500f5739,
- "orc"))
- .InSequence(s).WillOnce(Return(true));
- // Expectations are not wishes.
- EXPECT_CALL(handler, ExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
- "smurf"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValExpressionRuleUnchanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x666ae152)
- .Block("hideous")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x666ae152, "hideous"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValExpressionRuleChanged) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0xb5ca5c46)
- .Block("revolting")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0xb5ca5c46)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChanged", section);
-
- EXPECT_CALL(handler, ValExpressionRule(fde_start, 0xb5ca5c46, "revolting"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(fde_start + code_factor, 0xb5ca5c46))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0xb5ca5c46,
- "revolting"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-TEST_F(CFIRestore, RestoreValExpressionRuleChangedValExpression) {
- CFISection section(kLittleEndian, 4);
- StockCIEAndFDE(&section);
- section
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
- .Block("repulsive")
- .D8(dwarf2reader::DW_CFA_remember_state)
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_val_expression).ULEB128(0x500f5739)
- .Block("nauseous")
- .D8(dwarf2reader::DW_CFA_advance_loc | 1)
- .D8(dwarf2reader::DW_CFA_restore_state)
- .FinishEntry();
-
- PERHAPS_WRITE_DEBUG_FRAME_FILE("RestoreValExpressionRuleChangedValExpression",
- section);
-
- EXPECT_CALL(handler, ValExpressionRule(fde_start, 0x500f5739, "repulsive"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValExpressionRule(fde_start + code_factor, 0x500f5739,
- "nauseous"))
- .InSequence(s).WillOnce(Return(true));
- // Expectations are not wishes.
- EXPECT_CALL(handler, ValExpressionRule(fde_start + 2 * code_factor, 0x500f5739,
- "repulsive"))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End()).WillOnce(Return(true));
-
- ParseSection(&section);
-}
-
-struct EHFrameFixture: public CFIInsnFixture {
- EHFrameFixture()
- : CFIInsnFixture(), section(kBigEndian, 4, true) {
- encoded_pointer_bases.cfi = 0x7f496cb2;
- encoded_pointer_bases.text = 0x540f67b6;
- encoded_pointer_bases.data = 0xe3eab768;
- section.SetEncodedPointerBases(encoded_pointer_bases);
- }
- CFISection section;
- CFISection::EncodedPointerBases encoded_pointer_bases;
-
- // Parse CFIInsnFixture::ParseSection, but parse the section as
- // .eh_frame data, supplying stock base addresses.
- void ParseEHFrameSection(CFISection *section, bool succeeds = true) {
- EXPECT_TRUE(section->ContainsEHFrame());
- string contents;
- EXPECT_TRUE(section->GetContents(&contents));
- dwarf2reader::Endianness endianness;
- if (section->endianness() == kBigEndian)
- endianness = ENDIANNESS_BIG;
- else {
- assert(section->endianness() == kLittleEndian);
- endianness = ENDIANNESS_LITTLE;
- }
- ByteReader byte_reader(endianness);
- byte_reader.SetAddressSize(section->AddressSize());
- byte_reader.SetCFIDataBase(encoded_pointer_bases.cfi,
- reinterpret_cast<const uint8_t *>(contents.data()));
- byte_reader.SetTextBase(encoded_pointer_bases.text);
- byte_reader.SetDataBase(encoded_pointer_bases.data);
- CallFrameInfo parser(reinterpret_cast<const uint8_t *>(contents.data()),
- contents.size(),
- &byte_reader, &handler, &reporter, true);
- if (succeeds)
- EXPECT_TRUE(parser.Start());
- else
- EXPECT_FALSE(parser.Start());
- }
-
-};
-
-class EHFrame: public EHFrameFixture, public Test { };
-
-// A simple CIE, an FDE, and a terminator.
-TEST_F(EHFrame, Terminator) {
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(9968, 2466, 67, 1, "")
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3772).ULEB128(1372)
- .FinishEntry()
- .FDEHeader(cie, 0x848037a1, 0x7b30475e)
- .D8(dwarf2reader::DW_CFA_set_loc).D32(0x17713850)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(5721)
- .FinishEntry()
- .D32(0) // Terminate the sequence.
- // This FDE should be ignored.
- .FDEHeader(cie, 0xf19629fe, 0x439fb09b)
- .FinishEntry();
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.Terminator", section);
-
- EXPECT_CALL(handler, Entry(_, 0x848037a1, 0x7b30475e, 1, "", 67))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(0x848037a1, kCFARegister, 3772, 1372))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(0x17713850, 5721))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(reporter, EarlyEHTerminator(_))
- .InSequence(s).WillOnce(Return());
-
- ParseEHFrameSection(&section);
-}
-
-// The parser should recognize the Linux Standards Base 'z' augmentations.
-TEST_F(EHFrame, SimpleFDE) {
- DwarfPointerEncoding lsda_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_indirect
- | dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_sdata2);
- DwarfPointerEncoding fde_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_udata2);
-
- section.SetPointerEncoding(fde_encoding);
- section.SetEncodedPointerBases(encoded_pointer_bases);
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(4873, 7012, 100, 1, "zSLPR")
- .ULEB128(7) // Augmentation data length
- .D8(lsda_encoding) // LSDA pointer format
- .D8(dwarf2reader::DW_EH_PE_pcrel) // personality pointer format
- .EncodedPointer(0x97baa00, dwarf2reader::DW_EH_PE_pcrel) // and value
- .D8(fde_encoding) // FDE pointer format
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(6706).ULEB128(31)
- .FinishEntry()
- .FDEHeader(cie, 0x540f6b56, 0xf686)
- .ULEB128(2) // Augmentation data length
- .EncodedPointer(0xe3eab475, lsda_encoding) // LSDA pointer, signed
- .D8(dwarf2reader::DW_CFA_set_loc)
- .EncodedPointer(0x540fa4ce, fde_encoding)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(0x675e)
- .FinishEntry()
- .D32(0); // terminator
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.SimpleFDE", section);
-
- EXPECT_CALL(handler, Entry(_, 0x540f6b56, 0xf686, 1, "zSLPR", 100))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, PersonalityRoutine(0x97baa00, false))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, LanguageSpecificDataArea(0xe3eab475, true))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, SignalHandler())
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(0x540f6b56, kCFARegister, 6706, 31))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(0x540fa4ce, 0x675e))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-// Check that we can handle an empty 'z' augmentation.
-TEST_F(EHFrame, EmptyZ) {
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(5955, 5805, 228, 1, "z")
- .ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(3629).ULEB128(247)
- .FinishEntry()
- .FDEHeader(cie, 0xda007738, 0xfb55c641)
- .ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_advance_loc1).D8(11)
- .D8(dwarf2reader::DW_CFA_undefined).ULEB128(3769)
- .FinishEntry();
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.EmptyZ", section);
-
- EXPECT_CALL(handler, Entry(_, 0xda007738, 0xfb55c641, 1, "z", 228))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, ValOffsetRule(0xda007738, kCFARegister, 3629, 247))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, UndefinedRule(0xda007738 + 11 * 5955, 3769))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-// Check that we recognize bad 'z' augmentation characters.
-TEST_F(EHFrame, BadZ) {
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(6937, 1045, 142, 1, "zQ")
- .ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_def_cfa).ULEB128(9006).ULEB128(7725)
- .FinishEntry()
- .FDEHeader(cie, 0x1293efa8, 0x236f53f2)
- .ULEB128(0) // Augmentation data length
- .D8(dwarf2reader::DW_CFA_advance_loc | 12)
- .D8(dwarf2reader::DW_CFA_register).ULEB128(5667).ULEB128(3462)
- .FinishEntry();
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.BadZ", section);
-
- EXPECT_CALL(reporter, UnrecognizedAugmentation(_, "zQ"))
- .WillOnce(Return());
-
- ParseEHFrameSection(&section, false);
-}
-
-TEST_F(EHFrame, zL) {
- Label cie;
- DwarfPointerEncoding lsda_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_funcrel
- | dwarf2reader::DW_EH_PE_udata2);
- section
- .Mark(&cie)
- .CIEHeader(9285, 9959, 54, 1, "zL")
- .ULEB128(1) // Augmentation data length
- .D8(lsda_encoding) // encoding for LSDA pointer in FDE
-
- .FinishEntry()
- .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
- .ULEB128(2) // Augmentation data length
- .EncodedPointer(0xd40099cd, lsda_encoding) // LSDA pointer
- .FinishEntry()
- .D32(0); // terminator
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zL", section);
-
- EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zL", 54))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, LanguageSpecificDataArea(0xd40099cd, false))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-TEST_F(EHFrame, zP) {
- Label cie;
- DwarfPointerEncoding personality_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_datarel
- | dwarf2reader::DW_EH_PE_udata2);
- section
- .Mark(&cie)
- .CIEHeader(1097, 6313, 17, 1, "zP")
- .ULEB128(3) // Augmentation data length
- .D8(personality_encoding) // encoding for personality routine
- .EncodedPointer(0xe3eaccac, personality_encoding) // value
- .FinishEntry()
- .FDEHeader(cie, 0x0c8350c9, 0xbef11087)
- .ULEB128(0) // Augmentation data length
- .FinishEntry()
- .D32(0); // terminator
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zP", section);
-
- EXPECT_CALL(handler, Entry(_, 0x0c8350c9, 0xbef11087, 1, "zP", 17))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, PersonalityRoutine(0xe3eaccac, false))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-TEST_F(EHFrame, zR) {
- Label cie;
- DwarfPointerEncoding pointer_encoding =
- DwarfPointerEncoding(dwarf2reader::DW_EH_PE_textrel
- | dwarf2reader::DW_EH_PE_sdata2);
- section.SetPointerEncoding(pointer_encoding);
- section
- .Mark(&cie)
- .CIEHeader(8011, 5496, 75, 1, "zR")
- .ULEB128(1) // Augmentation data length
- .D8(pointer_encoding) // encoding for FDE addresses
- .FinishEntry()
- .FDEHeader(cie, 0x540f9431, 0xbd0)
- .ULEB128(0) // Augmentation data length
- .FinishEntry()
- .D32(0); // terminator
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zR", section);
-
- EXPECT_CALL(handler, Entry(_, 0x540f9431, 0xbd0, 1, "zR", 75))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-TEST_F(EHFrame, zS) {
- Label cie;
- section
- .Mark(&cie)
- .CIEHeader(9217, 7694, 57, 1, "zS")
- .ULEB128(0) // Augmentation data length
- .FinishEntry()
- .FDEHeader(cie, 0xd40091aa, 0x9aa6e746)
- .ULEB128(0) // Augmentation data length
- .FinishEntry()
- .D32(0); // terminator
-
- PERHAPS_WRITE_EH_FRAME_FILE("EHFrame.zS", section);
-
- EXPECT_CALL(handler, Entry(_, 0xd40091aa, 0x9aa6e746, 1, "zS", 57))
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, SignalHandler())
- .InSequence(s).WillOnce(Return(true));
- EXPECT_CALL(handler, End())
- .InSequence(s).WillOnce(Return(true));
-
- ParseEHFrameSection(&section);
-}
-
-// These tests require manual inspection of the test output.
-struct CFIReporterFixture {
- CFIReporterFixture() : reporter("test file name", "test section name") { }
- CallFrameInfo::Reporter reporter;
-};
-
-class CFIReporter: public CFIReporterFixture, public Test { };
-
-TEST_F(CFIReporter, Incomplete) {
- reporter.Incomplete(0x0102030405060708ULL, CallFrameInfo::kUnknown);
-}
-
-TEST_F(CFIReporter, EarlyEHTerminator) {
- reporter.EarlyEHTerminator(0x0102030405060708ULL);
-}
-
-TEST_F(CFIReporter, CIEPointerOutOfRange) {
- reporter.CIEPointerOutOfRange(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, BadCIEId) {
- reporter.BadCIEId(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, UnrecognizedVersion) {
- reporter.UnrecognizedVersion(0x0123456789abcdefULL, 43);
-}
-
-TEST_F(CFIReporter, UnrecognizedAugmentation) {
- reporter.UnrecognizedAugmentation(0x0123456789abcdefULL, "poodles");
-}
-
-TEST_F(CFIReporter, InvalidPointerEncoding) {
- reporter.InvalidPointerEncoding(0x0123456789abcdefULL, 0x42);
-}
-
-TEST_F(CFIReporter, UnusablePointerEncoding) {
- reporter.UnusablePointerEncoding(0x0123456789abcdefULL, 0x42);
-}
-
-TEST_F(CFIReporter, RestoreInCIE) {
- reporter.RestoreInCIE(0x0123456789abcdefULL, 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, BadInstruction) {
- reporter.BadInstruction(0x0123456789abcdefULL, CallFrameInfo::kFDE,
- 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, NoCFARule) {
- reporter.NoCFARule(0x0123456789abcdefULL, CallFrameInfo::kCIE,
- 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, EmptyStateStack) {
- reporter.EmptyStateStack(0x0123456789abcdefULL, CallFrameInfo::kTerminator,
- 0xfedcba9876543210ULL);
-}
-
-TEST_F(CFIReporter, ClearingCFARule) {
- reporter.ClearingCFARule(0x0123456789abcdefULL, CallFrameInfo::kFDE,
- 0xfedcba9876543210ULL);
-}
-
-#ifdef WRITE_ELF
-// See comments at the top of the file mentioning WRITE_ELF for details.
-
-using google_breakpad::test_assembler::Section;
-
-struct ELFSectionHeader {
- ELFSectionHeader(unsigned int set_type)
- : type(set_type), flags(0), address(0), link(0), info(0),
- alignment(1), entry_size(0) { }
- Label name;
- unsigned int type;
- uint64_t flags;
- uint64_t address;
- Label file_offset;
- Label file_size;
- unsigned int link;
- unsigned int info;
- uint64_t alignment;
- uint64_t entry_size;
-};
-
-void AppendSectionHeader(CFISection *table, const ELFSectionHeader &header) {
- (*table)
- .D32(header.name) // name, index in string tbl
- .D32(header.type) // type
- .Address(header.flags) // flags
- .Address(header.address) // address in memory
- .Address(header.file_offset) // offset in ELF file
- .Address(header.file_size) // length in bytes
- .D32(header.link) // link to related section
- .D32(header.info) // miscellaneous
- .Address(header.alignment) // alignment
- .Address(header.entry_size); // entry size
-}
-
-void WriteELFFrameSection(const char *filename, const char *cfi_name,
- const CFISection &cfi) {
- int elf_class = cfi.AddressSize() == 4 ? ELFCLASS32 : ELFCLASS64;
- int elf_data = (cfi.endianness() == kBigEndian
- ? ELFDATA2MSB : ELFDATA2LSB);
- CFISection elf(cfi.endianness(), cfi.AddressSize());
- Label elf_header_size, section_table_offset;
- elf
- .Append("\x7f" "ELF")
- .D8(elf_class) // 32-bit or 64-bit ELF
- .D8(elf_data) // endianness
- .D8(1) // ELF version
- .D8(ELFOSABI_LINUX) // Operating System/ABI indication
- .D8(0) // ABI version
- .Append(7, 0xda) // padding
- .D16(ET_EXEC) // file type: executable file
- .D16(EM_386) // architecture: Intel IA-32
- .D32(EV_CURRENT); // ELF version
- elf
- .Address(0x0123456789abcdefULL) // program entry point
- .Address(0) // program header offset
- .Address(section_table_offset) // section header offset
- .D32(0) // processor-specific flags
- .D16(elf_header_size) // ELF header size in bytes */
- .D16(elf_class == ELFCLASS32 ? 32 : 56) // program header entry size
- .D16(0) // program header table entry count
- .D16(elf_class == ELFCLASS32 ? 40 : 64) // section header entry size
- .D16(3) // section count
- .D16(1) // section name string table
- .Mark(&elf_header_size);
-
- // The null section. Every ELF file has one, as the first entry in
- // the section header table.
- ELFSectionHeader null_header(SHT_NULL);
- null_header.file_offset = 0;
- null_header.file_size = 0;
-
- // The CFI section. The whole reason for writing out this ELF file
- // is to put this in it so that we can run other dumping programs on
- // it to check its contents.
- ELFSectionHeader cfi_header(SHT_PROGBITS);
- cfi_header.file_size = cfi.Size();
-
- // The section holding the names of the sections. This is the
- // section whose index appears in the e_shstrndx member of the ELF
- // header.
- ELFSectionHeader section_names_header(SHT_STRTAB);
- CFISection section_names(cfi.endianness(), cfi.AddressSize());
- section_names
- .Mark(&null_header.name)
- .AppendCString("")
- .Mark(&section_names_header.name)
- .AppendCString(".shstrtab")
- .Mark(&cfi_header.name)
- .AppendCString(cfi_name)
- .Mark(&section_names_header.file_size);
-
- // Create the section table. The ELF header's e_shoff member refers
- // to this, and the e_shnum member gives the number of entries it
- // contains.
- CFISection section_table(cfi.endianness(), cfi.AddressSize());
- AppendSectionHeader(&section_table, null_header);
- AppendSectionHeader(&section_table, section_names_header);
- AppendSectionHeader(&section_table, cfi_header);
-
- // Append the section table and the section contents to the ELF file.
- elf
- .Mark(&section_table_offset)
- .Append(section_table)
- .Mark(&section_names_header.file_offset)
- .Append(section_names)
- .Mark(&cfi_header.file_offset)
- .Append(cfi);
-
- string contents;
- if (!elf.GetContents(&contents)) {
- fprintf(stderr, "failed to get ELF file contents\n");
- exit(1);
- }
-
- FILE *out = fopen(filename, "w");
- if (!out) {
- fprintf(stderr, "error opening ELF file '%s': %s\n",
- filename, strerror(errno));
- exit(1);
- }
-
- if (fwrite(contents.data(), 1, contents.size(), out) != contents.size()) {
- fprintf(stderr, "error writing ELF data to '%s': %s\n",
- filename, strerror(errno));
- exit(1);
- }
-
- if (fclose(out) == EOF) {
- fprintf(stderr, "error closing ELF file '%s': %s\n",
- filename, strerror(errno));
- exit(1);
- }
-}
-#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc
deleted file mode 100644
index 71418eb8d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_die_unittest.cc
+++ /dev/null
@@ -1,487 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2reader_die_unittest.cc: Unit tests for dwarf2reader::CompilationUnit
-
-#include <stdint.h>
-#include <stdlib.h>
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/dwarf2reader_test_common.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-using google_breakpad::test_assembler::Endianness;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::Section;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-
-using dwarf2reader::ByteReader;
-using dwarf2reader::CompilationUnit;
-using dwarf2reader::Dwarf2Handler;
-using dwarf2reader::DwarfAttribute;
-using dwarf2reader::DwarfForm;
-using dwarf2reader::DwarfHasChild;
-using dwarf2reader::DwarfTag;
-using dwarf2reader::ENDIANNESS_BIG;
-using dwarf2reader::ENDIANNESS_LITTLE;
-using dwarf2reader::SectionMap;
-
-using std::vector;
-using testing::InSequence;
-using testing::Pointee;
-using testing::Return;
-using testing::Sequence;
-using testing::Test;
-using testing::TestWithParam;
-using testing::_;
-
-class MockDwarf2Handler: public Dwarf2Handler {
- public:
- MOCK_METHOD5(StartCompilationUnit, bool(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version));
- MOCK_METHOD2(StartDIE, bool(uint64 offset, enum DwarfTag tag));
- MOCK_METHOD4(ProcessAttributeUnsigned, void(uint64 offset,
- DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data));
- MOCK_METHOD4(ProcessAttributeSigned, void(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data));
- MOCK_METHOD4(ProcessAttributeReference, void(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data));
- MOCK_METHOD5(ProcessAttributeBuffer, void(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const uint8_t *data,
- uint64 len));
- MOCK_METHOD4(ProcessAttributeString, void(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string& data));
- MOCK_METHOD4(ProcessAttributeSignature, void(uint64 offset,
- DwarfAttribute attr,
- enum DwarfForm form,
- uint64 signature));
- MOCK_METHOD1(EndDIE, void(uint64 offset));
-};
-
-struct DIEFixture {
-
- DIEFixture() {
- // Fix the initial offset of the .debug_info and .debug_abbrev sections.
- info.start() = 0;
- abbrevs.start() = 0;
-
- // Default expectations for the data handler.
- EXPECT_CALL(handler, StartCompilationUnit(_, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, StartDIE(_, _)).Times(0);
- EXPECT_CALL(handler, ProcessAttributeUnsigned(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, ProcessAttributeSigned(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, ProcessAttributeReference(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, ProcessAttributeBuffer(_, _, _, _, _)).Times(0);
- EXPECT_CALL(handler, ProcessAttributeString(_, _, _, _)).Times(0);
- EXPECT_CALL(handler, EndDIE(_)).Times(0);
- }
-
- // Return a reference to a section map whose .debug_info section refers
- // to |info|, and whose .debug_abbrev section refers to |abbrevs|. This
- // function returns a reference to the same SectionMap each time; new
- // calls wipe out maps established by earlier calls.
- const SectionMap &MakeSectionMap() {
- // Copy the sections' contents into strings that will live as long as
- // the map itself.
- assert(info.GetContents(&info_contents));
- assert(abbrevs.GetContents(&abbrevs_contents));
- section_map.clear();
- section_map[".debug_info"].first
- = reinterpret_cast<const uint8_t *>(info_contents.data());
- section_map[".debug_info"].second = info_contents.size();
- section_map[".debug_abbrev"].first
- = reinterpret_cast<const uint8_t *>(abbrevs_contents.data());
- section_map[".debug_abbrev"].second = abbrevs_contents.size();
- return section_map;
- }
-
- TestCompilationUnit info;
- TestAbbrevTable abbrevs;
- MockDwarf2Handler handler;
- string abbrevs_contents, info_contents;
- SectionMap section_map;
-};
-
-struct DwarfHeaderParams {
- DwarfHeaderParams(Endianness endianness, size_t format_size,
- int version, size_t address_size)
- : endianness(endianness), format_size(format_size),
- version(version), address_size(address_size) { }
- Endianness endianness;
- size_t format_size; // 4-byte or 8-byte DWARF offsets
- int version;
- size_t address_size;
-};
-
-class DwarfHeader: public DIEFixture,
- public TestWithParam<DwarfHeaderParams> { };
-
-TEST_P(DwarfHeader, Header) {
- Label abbrev_table = abbrevs.Here();
- abbrevs.Abbrev(1, dwarf2reader::DW_TAG_compile_unit,
- dwarf2reader::DW_children_yes)
- .Attribute(dwarf2reader::DW_AT_name, dwarf2reader::DW_FORM_string)
- .EndAbbrev()
- .EndTable();
-
- info.set_format_size(GetParam().format_size);
- info.set_endianness(GetParam().endianness);
-
- info.Header(GetParam().version, abbrev_table, GetParam().address_size)
- .ULEB128(1) // DW_TAG_compile_unit, with children
- .AppendCString("sam") // DW_AT_name, DW_FORM_string
- .D8(0); // end of children
- info.Finish();
-
- {
- InSequence s;
- EXPECT_CALL(handler,
- StartCompilationUnit(0, GetParam().address_size,
- GetParam().format_size, _,
- GetParam().version))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, StartDIE(_, dwarf2reader::DW_TAG_compile_unit))
- .WillOnce(Return(true));
- EXPECT_CALL(handler, ProcessAttributeString(_, dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_string,
- "sam"))
- .WillOnce(Return());
- EXPECT_CALL(handler, EndDIE(_))
- .WillOnce(Return());
- }
-
- ByteReader byte_reader(GetParam().endianness == kLittleEndian ?
- ENDIANNESS_LITTLE : ENDIANNESS_BIG);
- CompilationUnit parser("", MakeSectionMap(), 0, &byte_reader, &handler);
- EXPECT_EQ(parser.Start(), info_contents.size());
-}
-
-INSTANTIATE_TEST_CASE_P(
- HeaderVariants, DwarfHeader,
- ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
- DwarfHeaderParams(kLittleEndian, 4, 2, 8),
- DwarfHeaderParams(kLittleEndian, 4, 3, 4),
- DwarfHeaderParams(kLittleEndian, 4, 3, 8),
- DwarfHeaderParams(kLittleEndian, 4, 4, 4),
- DwarfHeaderParams(kLittleEndian, 4, 4, 8),
- DwarfHeaderParams(kLittleEndian, 8, 2, 4),
- DwarfHeaderParams(kLittleEndian, 8, 2, 8),
- DwarfHeaderParams(kLittleEndian, 8, 3, 4),
- DwarfHeaderParams(kLittleEndian, 8, 3, 8),
- DwarfHeaderParams(kLittleEndian, 8, 4, 4),
- DwarfHeaderParams(kLittleEndian, 8, 4, 8),
- DwarfHeaderParams(kBigEndian, 4, 2, 4),
- DwarfHeaderParams(kBigEndian, 4, 2, 8),
- DwarfHeaderParams(kBigEndian, 4, 3, 4),
- DwarfHeaderParams(kBigEndian, 4, 3, 8),
- DwarfHeaderParams(kBigEndian, 4, 4, 4),
- DwarfHeaderParams(kBigEndian, 4, 4, 8),
- DwarfHeaderParams(kBigEndian, 8, 2, 4),
- DwarfHeaderParams(kBigEndian, 8, 2, 8),
- DwarfHeaderParams(kBigEndian, 8, 3, 4),
- DwarfHeaderParams(kBigEndian, 8, 3, 8),
- DwarfHeaderParams(kBigEndian, 8, 4, 4),
- DwarfHeaderParams(kBigEndian, 8, 4, 8)));
-
-struct DwarfFormsFixture: public DIEFixture {
- // Start a compilation unit, as directed by |params|, containing one
- // childless DIE of the given tag, with one attribute of the given name
- // and form. The 'info' fixture member is left just after the abbrev
- // code, waiting for the attribute value to be appended.
- void StartSingleAttributeDIE(const DwarfHeaderParams &params,
- DwarfTag tag, DwarfAttribute name,
- DwarfForm form) {
- // Create the abbreviation table.
- Label abbrev_table = abbrevs.Here();
- abbrevs.Abbrev(1, tag, dwarf2reader::DW_children_no)
- .Attribute(name, form)
- .EndAbbrev()
- .EndTable();
-
- // Create the compilation unit, up to the attribute value.
- info.set_format_size(params.format_size);
- info.set_endianness(params.endianness);
- info.Header(params.version, abbrev_table, params.address_size)
- .ULEB128(1); // abbrev code
- }
-
- // Set up handler to expect a compilation unit matching |params|,
- // containing one childless DIE of the given tag, in the sequence s. Stop
- // just before the expectations.
- void ExpectBeginCompilationUnit(const DwarfHeaderParams &params,
- DwarfTag tag, uint64 offset=0) {
- EXPECT_CALL(handler,
- StartCompilationUnit(offset, params.address_size,
- params.format_size, _,
- params.version))
- .InSequence(s)
- .WillOnce(Return(true));
- EXPECT_CALL(handler, StartDIE(_, tag))
- .InSequence(s)
- .WillOnce(Return(true));
- }
-
- void ExpectEndCompilationUnit() {
- EXPECT_CALL(handler, EndDIE(_))
- .InSequence(s)
- .WillOnce(Return());
- }
-
- void ParseCompilationUnit(const DwarfHeaderParams &params, uint64 offset=0) {
- ByteReader byte_reader(params.endianness == kLittleEndian ?
- ENDIANNESS_LITTLE : ENDIANNESS_BIG);
- CompilationUnit parser("", MakeSectionMap(), offset, &byte_reader, &handler);
- EXPECT_EQ(offset + parser.Start(), info_contents.size());
- }
-
- // The sequence to which the fixture's methods append expectations.
- Sequence s;
-};
-
-struct DwarfForms: public DwarfFormsFixture,
- public TestWithParam<DwarfHeaderParams> { };
-
-TEST_P(DwarfForms, addr) {
- StartSingleAttributeDIE(GetParam(), dwarf2reader::DW_TAG_compile_unit,
- dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr);
- uint64_t value;
- if (GetParam().address_size == 4) {
- value = 0xc8e9ffcc;
- info.D32(value);
- } else {
- value = 0xe942517fc2768564ULL;
- info.D64(value);
- }
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), dwarf2reader::DW_TAG_compile_unit);
- EXPECT_CALL(handler, ProcessAttributeUnsigned(_, dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr,
- value))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, block2_empty) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
- (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2);
- info.D16(0);
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
- EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2,
- _, 0))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, block2) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x16e4d2f7,
- (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2);
- unsigned char data[258];
- memset(data, '*', sizeof(data));
- info.D16(sizeof(data))
- .Append(data, sizeof(data));
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x16e4d2f7);
- EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xe52c4463,
- dwarf2reader::DW_FORM_block2,
- Pointee('*'), 258))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, flag_present) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x3e449ac2,
- (DwarfAttribute) 0x359d1972,
- dwarf2reader::DW_FORM_flag_present);
- // DW_FORM_flag_present occupies no space in the DIE.
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x3e449ac2);
- EXPECT_CALL(handler,
- ProcessAttributeUnsigned(_, (DwarfAttribute) 0x359d1972,
- dwarf2reader::DW_FORM_flag_present,
- 1))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, sec_offset) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x1d971689,
- (DwarfAttribute) 0xa060bfd1,
- dwarf2reader::DW_FORM_sec_offset);
- uint64_t value;
- if (GetParam().format_size == 4) {
- value = 0xacc9c388;
- info.D32(value);
- } else {
- value = 0xcffe5696ffe3ed0aULL;
- info.D64(value);
- }
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x1d971689);
- EXPECT_CALL(handler, ProcessAttributeUnsigned(_, (DwarfAttribute) 0xa060bfd1,
- dwarf2reader::DW_FORM_sec_offset,
- value))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, exprloc) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0xb6d167bb,
- (DwarfAttribute) 0xba3ae5cb,
- dwarf2reader::DW_FORM_exprloc);
- info.ULEB128(29)
- .Append(29, 173);
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0xb6d167bb);
- EXPECT_CALL(handler, ProcessAttributeBuffer(_, (DwarfAttribute) 0xba3ae5cb,
- dwarf2reader::DW_FORM_exprloc,
- Pointee(173), 29))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-TEST_P(DwarfForms, ref_sig8) {
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
- (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8);
- info.D64(0xf72fa0cb6ddcf9d6ULL);
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b);
- EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8,
- 0xf72fa0cb6ddcf9d6ULL))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam());
-}
-
-// A value passed to ProcessAttributeSignature is just an absolute number,
-// not an offset within the compilation unit as most of the other
-// DW_FORM_ref forms are. Check that the reader doesn't try to apply any
-// offset to the signature, by reading it from a compilation unit that does
-// not start at the beginning of the section.
-TEST_P(DwarfForms, ref_sig8_not_first) {
- info.Append(98, '*');
- StartSingleAttributeDIE(GetParam(), (DwarfTag) 0x253e7b2b,
- (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8);
- info.D64(0xf72fa0cb6ddcf9d6ULL);
- info.Finish();
-
- ExpectBeginCompilationUnit(GetParam(), (DwarfTag) 0x253e7b2b, 98);
- EXPECT_CALL(handler, ProcessAttributeSignature(_, (DwarfAttribute) 0xd708d908,
- dwarf2reader::DW_FORM_ref_sig8,
- 0xf72fa0cb6ddcf9d6ULL))
- .InSequence(s)
- .WillOnce(Return());
- ExpectEndCompilationUnit();
-
- ParseCompilationUnit(GetParam(), 98);
-}
-
-// Tests for the other attribute forms could go here.
-
-INSTANTIATE_TEST_CASE_P(
- HeaderVariants, DwarfForms,
- ::testing::Values(DwarfHeaderParams(kLittleEndian, 4, 2, 4),
- DwarfHeaderParams(kLittleEndian, 4, 2, 8),
- DwarfHeaderParams(kLittleEndian, 4, 3, 4),
- DwarfHeaderParams(kLittleEndian, 4, 3, 8),
- DwarfHeaderParams(kLittleEndian, 4, 4, 4),
- DwarfHeaderParams(kLittleEndian, 4, 4, 8),
- DwarfHeaderParams(kLittleEndian, 8, 2, 4),
- DwarfHeaderParams(kLittleEndian, 8, 2, 8),
- DwarfHeaderParams(kLittleEndian, 8, 3, 4),
- DwarfHeaderParams(kLittleEndian, 8, 3, 8),
- DwarfHeaderParams(kLittleEndian, 8, 4, 4),
- DwarfHeaderParams(kLittleEndian, 8, 4, 8),
- DwarfHeaderParams(kBigEndian, 4, 2, 4),
- DwarfHeaderParams(kBigEndian, 4, 2, 8),
- DwarfHeaderParams(kBigEndian, 4, 3, 4),
- DwarfHeaderParams(kBigEndian, 4, 3, 8),
- DwarfHeaderParams(kBigEndian, 4, 4, 4),
- DwarfHeaderParams(kBigEndian, 4, 4, 8),
- DwarfHeaderParams(kBigEndian, 8, 2, 4),
- DwarfHeaderParams(kBigEndian, 8, 2, 8),
- DwarfHeaderParams(kBigEndian, 8, 3, 4),
- DwarfHeaderParams(kBigEndian, 8, 3, 8),
- DwarfHeaderParams(kBigEndian, 8, 4, 4),
- DwarfHeaderParams(kBigEndian, 8, 4, 8)));
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_test_common.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_test_common.h
deleted file mode 100644
index e91de9061..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/dwarf2reader_test_common.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// -*- mode: c++ -*-
-
-// Copyright (c) 2012, 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf2reader_test_common.h: Define TestCompilationUnit and
-// TestAbbrevTable, classes for creating properly (and improperly)
-// formatted DWARF compilation unit data for unit tests.
-
-#ifndef COMMON_DWARF_DWARF2READER_TEST_COMMON_H__
-#define COMMON_DWARF_DWARF2READER_TEST_COMMON_H__
-
-#include "common/test_assembler.h"
-#include "common/dwarf/dwarf2enums.h"
-
-// A subclass of test_assembler::Section, specialized for constructing
-// DWARF compilation units.
-class TestCompilationUnit: public google_breakpad::test_assembler::Section {
- public:
- typedef dwarf2reader::DwarfTag DwarfTag;
- typedef dwarf2reader::DwarfAttribute DwarfAttribute;
- typedef dwarf2reader::DwarfForm DwarfForm;
- typedef google_breakpad::test_assembler::Label Label;
-
- // Set the section's DWARF format size (the 32-bit DWARF format or the
- // 64-bit DWARF format, for lengths and section offsets --- not the
- // address size) to format_size.
- void set_format_size(size_t format_size) {
- assert(format_size == 4 || format_size == 8);
- format_size_ = format_size;
- }
-
- // Append a DWARF section offset value, of the appropriate size for this
- // compilation unit.
- template<typename T>
- void SectionOffset(T offset) {
- if (format_size_ == 4)
- D32(offset);
- else
- D64(offset);
- }
-
- // Append a DWARF compilation unit header to the section, with the given
- // DWARF version, abbrev table offset, and address size.
- TestCompilationUnit &Header(int version, const Label &abbrev_offset,
- size_t address_size) {
- if (format_size_ == 4) {
- D32(length_);
- } else {
- D32(0xffffffff);
- D64(length_);
- }
- post_length_offset_ = Size();
- D16(version);
- SectionOffset(abbrev_offset);
- D8(address_size);
- return *this;
- }
-
- // Mark the end of this header's DIEs.
- TestCompilationUnit &Finish() {
- length_ = Size() - post_length_offset_;
- return *this;
- }
-
- private:
- // The DWARF format size for this compilation unit.
- size_t format_size_;
-
- // The offset of the point in the compilation unit header immediately
- // after the initial length field.
- uint64_t post_length_offset_;
-
- // The length of the compilation unit, not including the initial length field.
- Label length_;
-};
-
-// A subclass of test_assembler::Section specialized for constructing DWARF
-// abbreviation tables.
-class TestAbbrevTable: public google_breakpad::test_assembler::Section {
- public:
- typedef dwarf2reader::DwarfTag DwarfTag;
- typedef dwarf2reader::DwarfAttribute DwarfAttribute;
- typedef dwarf2reader::DwarfForm DwarfForm;
- typedef dwarf2reader::DwarfHasChild DwarfHasChild;
- typedef google_breakpad::test_assembler::Label Label;
-
- // Start a new abbreviation table entry for abbreviation code |code|,
- // encoding a DIE whose tag is |tag|, and which has children if and only
- // if |has_children| is true.
- TestAbbrevTable &Abbrev(int code, DwarfTag tag, DwarfHasChild has_children) {
- assert(code != 0);
- ULEB128(code);
- ULEB128(static_cast<unsigned>(tag));
- D8(static_cast<unsigned>(has_children));
- return *this;
- };
-
- // Add an attribute to the current abbreviation code whose name is |name|
- // and whose form is |form|.
- TestAbbrevTable &Attribute(DwarfAttribute name, DwarfForm form) {
- ULEB128(static_cast<unsigned>(name));
- ULEB128(static_cast<unsigned>(form));
- return *this;
- }
-
- // Finish the current abbreviation code.
- TestAbbrevTable &EndAbbrev() {
- ULEB128(0);
- ULEB128(0);
- return *this;
- }
-
- // Finish the current abbreviation table.
- TestAbbrevTable &EndTable() {
- ULEB128(0);
- return *this;
- }
-};
-
-#endif // COMMON_DWARF_DWARF2READER_TEST_COMMON_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.cc
deleted file mode 100644
index 4135a51a9..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.cc
+++ /dev/null
@@ -1,1273 +0,0 @@
-// Copyright 2005 Google Inc. All Rights Reserved.
-// Author: chatham@google.com (Andrew Chatham)
-// Author: satorux@google.com (Satoru Takabayashi)
-//
-// Code for reading in ELF files.
-//
-// For information on the ELF format, see
-// http://www.x86.org/ftp/manuals/tools/elf.pdf
-//
-// I also liked:
-// http://www.caldera.com/developers/gabi/1998-04-29/contents.html
-//
-// A note about types: When dealing with the file format, we use types
-// like Elf32_Word, but in the public interfaces we treat all
-// addresses as uint64. As a result, we should be able to symbolize
-// 64-bit binaries from a 32-bit process (which we don't do,
-// anyway). size_t should therefore be avoided, except where required
-// by things like mmap().
-//
-// Although most of this code can deal with arbitrary ELF files of
-// either word size, the public ElfReader interface only examines
-// files loaded into the current address space, which must all match
-// __WORDSIZE. This code cannot handle ELF files with a non-native
-// byte ordering.
-//
-// TODO(chatham): It would be nice if we could accomplish this task
-// without using malloc(), so we could use it as the process is dying.
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE // needed for pread()
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include <algorithm>
-#include <map>
-#include <string>
-#include <vector>
-// TODO(saugustine): Add support for compressed debug.
-// Also need to add configure tests for zlib.
-//#include "zlib.h"
-
-#include "third_party/musl/include/elf.h"
-#include "elf_reader.h"
-#include "common/using_std_string.h"
-
-// EM_AARCH64 is not defined by elf.h of GRTE v3 on x86.
-// TODO(dougkwan): Remove this when v17 is retired.
-#if !defined(EM_AARCH64)
-#define EM_AARCH64 183 /* ARM AARCH64 */
-#endif
-
-// Map Linux macros to their Apple equivalents.
-#if __APPLE__
-#ifndef __LITTLE_ENDIAN
-#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
-#endif // __LITTLE_ENDIAN
-#ifndef __BIG_ENDIAN
-#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
-#endif // __BIG_ENDIAN
-#ifndef __BYTE_ORDER
-#define __BYTE_ORDER __BYTE_ORDER__
-#endif // __BYTE_ORDER
-#endif // __APPLE__
-
-// TODO(dthomson): Can be removed once all Java code is using the Google3
-// launcher. We need to avoid processing PLT functions as it causes memory
-// fragmentation in malloc, which is fixed in tcmalloc - and if the Google3
-// launcher is used the JVM will then use tcmalloc. b/13735638
-//DEFINE_bool(elfreader_process_dynsyms, true,
-// "Activate PLT function processing");
-
-using std::vector;
-
-namespace {
-
-// The lowest bit of an ARM symbol value is used to indicate a Thumb address.
-const int kARMThumbBitOffset = 0;
-
-// Converts an ARM Thumb symbol value to a true aligned address value.
-template <typename T>
-T AdjustARMThumbSymbolValue(const T& symbol_table_value) {
- return symbol_table_value & ~(1 << kARMThumbBitOffset);
-}
-
-// Names of PLT-related sections.
-const char kElfPLTRelSectionName[] = ".rel.plt"; // Use Rel struct.
-const char kElfPLTRelaSectionName[] = ".rela.plt"; // Use Rela struct.
-const char kElfPLTSectionName[] = ".plt";
-const char kElfDynSymSectionName[] = ".dynsym";
-
-const int kX86PLTCodeSize = 0x10; // Size of one x86 PLT function in bytes.
-const int kARMPLTCodeSize = 0xc;
-const int kAARCH64PLTCodeSize = 0x10;
-
-const int kX86PLT0Size = 0x10; // Size of the special PLT0 entry.
-const int kARMPLT0Size = 0x14;
-const int kAARCH64PLT0Size = 0x20;
-
-// Suffix for PLT functions when it needs to be explicitly identified as such.
-const char kPLTFunctionSuffix[] = "@plt";
-
-} // namespace
-
-namespace dwarf2reader {
-
-template <class ElfArch> class ElfReaderImpl;
-
-// 32-bit and 64-bit ELF files are processed exactly the same, except
-// for various field sizes. Elf32 and Elf64 encompass all of the
-// differences between the two formats, and all format-specific code
-// in this file is templated on one of them.
-class Elf32 {
- public:
- typedef Elf32_Ehdr Ehdr;
- typedef Elf32_Shdr Shdr;
- typedef Elf32_Phdr Phdr;
- typedef Elf32_Word Word;
- typedef Elf32_Sym Sym;
- typedef Elf32_Rel Rel;
- typedef Elf32_Rela Rela;
-
- // What should be in the EI_CLASS header.
- static const int kElfClass = ELFCLASS32;
-
- // Given a symbol pointer, return the binding type (eg STB_WEAK).
- static char Bind(const Elf32_Sym *sym) {
- return ELF32_ST_BIND(sym->st_info);
- }
- // Given a symbol pointer, return the symbol type (eg STT_FUNC).
- static char Type(const Elf32_Sym *sym) {
- return ELF32_ST_TYPE(sym->st_info);
- }
-
- // Extract the symbol index from the r_info field of a relocation.
- static int r_sym(const Elf32_Word r_info) {
- return ELF32_R_SYM(r_info);
- }
-};
-
-
-class Elf64 {
- public:
- typedef Elf64_Ehdr Ehdr;
- typedef Elf64_Shdr Shdr;
- typedef Elf64_Phdr Phdr;
- typedef Elf64_Word Word;
- typedef Elf64_Sym Sym;
- typedef Elf64_Rel Rel;
- typedef Elf64_Rela Rela;
-
- // What should be in the EI_CLASS header.
- static const int kElfClass = ELFCLASS64;
-
- static char Bind(const Elf64_Sym *sym) {
- return ELF64_ST_BIND(sym->st_info);
- }
- static char Type(const Elf64_Sym *sym) {
- return ELF64_ST_TYPE(sym->st_info);
- }
- static int r_sym(const Elf64_Xword r_info) {
- return ELF64_R_SYM(r_info);
- }
-};
-
-
-// ElfSectionReader mmaps a section of an ELF file ("section" is ELF
-// terminology). The ElfReaderImpl object providing the section header
-// must exist for the lifetime of this object.
-//
-// The motivation for mmaping individual sections of the file is that
-// many Google executables are large enough when unstripped that we
-// have to worry about running out of virtual address space.
-//
-// For compressed sections we have no choice but to allocate memory.
-template<class ElfArch>
-class ElfSectionReader {
- public:
- ElfSectionReader(const char *name, const string &path, int fd,
- const typename ElfArch::Shdr &section_header)
- : contents_aligned_(NULL),
- contents_(NULL),
- header_(section_header) {
- // Back up to the beginning of the page we're interested in.
- const size_t additional = header_.sh_offset % getpagesize();
- const size_t offset_aligned = header_.sh_offset - additional;
- section_size_ = header_.sh_size;
- size_aligned_ = section_size_ + additional;
- // If the section has been stripped or is empty, do not attempt
- // to process its contents.
- if (header_.sh_type == SHT_NOBITS || header_.sh_size == 0)
- return;
- contents_aligned_ = mmap(NULL, size_aligned_, PROT_READ, MAP_SHARED,
- fd, offset_aligned);
- // Set where the offset really should begin.
- contents_ = reinterpret_cast<char *>(contents_aligned_) +
- (header_.sh_offset - offset_aligned);
-
- // Check for and handle any compressed contents.
- //if (strncmp(name, ".zdebug_", strlen(".zdebug_")) == 0)
- // DecompressZlibContents();
- // TODO(saugustine): Add support for proposed elf-section flag
- // "SHF_COMPRESS".
- }
-
- ~ElfSectionReader() {
- if (contents_aligned_ != NULL)
- munmap(contents_aligned_, size_aligned_);
- else
- delete[] contents_;
- }
-
- // Return the section header for this section.
- typename ElfArch::Shdr const &header() const { return header_; }
-
- // Return memory at the given offset within this section.
- const char *GetOffset(typename ElfArch::Word bytes) const {
- return contents_ + bytes;
- }
-
- const char *contents() const { return contents_; }
- size_t section_size() const { return section_size_; }
-
- private:
- // page-aligned file contents
- void *contents_aligned_;
- // contents as usable by the client. For non-compressed sections,
- // pointer within contents_aligned_ to where the section data
- // begins; for compressed sections, pointer to the decompressed
- // data.
- char *contents_;
- // size of contents_aligned_
- size_t size_aligned_;
- // size of contents.
- size_t section_size_;
- const typename ElfArch::Shdr header_;
-};
-
-// An iterator over symbols in a given section. It handles walking
-// through the entries in the specified section and mapping symbol
-// entries to their names in the appropriate string table (in
-// another section).
-template<class ElfArch>
-class SymbolIterator {
- public:
- SymbolIterator(ElfReaderImpl<ElfArch> *reader,
- typename ElfArch::Word section_type)
- : symbol_section_(reader->GetSectionByType(section_type)),
- string_section_(NULL),
- num_symbols_in_section_(0),
- symbol_within_section_(0) {
-
- // If this section type doesn't exist, leave
- // num_symbols_in_section_ as zero, so this iterator is already
- // done().
- if (symbol_section_ != NULL) {
- num_symbols_in_section_ = symbol_section_->header().sh_size /
- symbol_section_->header().sh_entsize;
-
- // Symbol sections have sh_link set to the section number of
- // the string section containing the symbol names.
- string_section_ = reader->GetSection(symbol_section_->header().sh_link);
- }
- }
-
- // Return true iff we have passed all symbols in this section.
- bool done() const {
- return symbol_within_section_ >= num_symbols_in_section_;
- }
-
- // Advance to the next symbol in this section.
- // REQUIRES: !done()
- void Next() { ++symbol_within_section_; }
-
- // Return a pointer to the current symbol.
- // REQUIRES: !done()
- const typename ElfArch::Sym *GetSymbol() const {
- return reinterpret_cast<const typename ElfArch::Sym*>(
- symbol_section_->GetOffset(symbol_within_section_ *
- symbol_section_->header().sh_entsize));
- }
-
- // Return the name of the current symbol, NULL if it has none.
- // REQUIRES: !done()
- const char *GetSymbolName() const {
- int name_offset = GetSymbol()->st_name;
- if (name_offset == 0)
- return NULL;
- return string_section_->GetOffset(name_offset);
- }
-
- int GetCurrentSymbolIndex() const {
- return symbol_within_section_;
- }
-
- private:
- const ElfSectionReader<ElfArch> *const symbol_section_;
- const ElfSectionReader<ElfArch> *string_section_;
- int num_symbols_in_section_;
- int symbol_within_section_;
-};
-
-
-// Copied from strings/strutil.h. Per chatham,
-// this library should not depend on strings.
-
-static inline bool MyHasSuffixString(const string& str, const string& suffix) {
- int len = str.length();
- int suflen = suffix.length();
- return (suflen <= len) && (str.compare(len-suflen, suflen, suffix) == 0);
-}
-
-
-// ElfReader loads an ELF binary and can provide information about its
-// contents. It is most useful for matching addresses to function
-// names. It does not understand debugging formats (eg dwarf2), so it
-// can't print line numbers. It takes a path to an elf file and a
-// readable file descriptor for that file, which it does not assume
-// ownership of.
-template<class ElfArch>
-class ElfReaderImpl {
- public:
- explicit ElfReaderImpl(const string &path, int fd)
- : path_(path),
- fd_(fd),
- section_headers_(NULL),
- program_headers_(NULL),
- opd_section_(NULL),
- base_for_text_(0),
- plts_supported_(false),
- plt_code_size_(0),
- plt0_size_(0),
- visited_relocation_entries_(false) {
- string error;
- is_dwp_ = MyHasSuffixString(path, ".dwp");
- ParseHeaders(fd, path);
- // Currently we need some extra information for PowerPC64 binaries
- // including a way to read the .opd section for function descriptors and a
- // way to find the linked base for function symbols.
- if (header_.e_machine == EM_PPC64) {
- // "opd_section_" must always be checked for NULL before use.
- opd_section_ = GetSectionInfoByName(".opd", &opd_info_);
- for (unsigned int k = 0u; k < GetNumSections(); ++k) {
- const char *name = GetSectionName(section_headers_[k].sh_name);
- if (strncmp(name, ".text", strlen(".text")) == 0) {
- base_for_text_ =
- section_headers_[k].sh_addr - section_headers_[k].sh_offset;
- break;
- }
- }
- }
- // Turn on PLTs.
- if (header_.e_machine == EM_386 || header_.e_machine == EM_X86_64) {
- plt_code_size_ = kX86PLTCodeSize;
- plt0_size_ = kX86PLT0Size;
- plts_supported_ = true;
- } else if (header_.e_machine == EM_ARM) {
- plt_code_size_ = kARMPLTCodeSize;
- plt0_size_ = kARMPLT0Size;
- plts_supported_ = true;
- } else if (header_.e_machine == EM_AARCH64) {
- plt_code_size_ = kAARCH64PLTCodeSize;
- plt0_size_ = kAARCH64PLT0Size;
- plts_supported_ = true;
- }
- }
-
- ~ElfReaderImpl() {
- for (unsigned int i = 0u; i < sections_.size(); ++i)
- delete sections_[i];
- delete [] section_headers_;
- delete [] program_headers_;
- }
-
- // Examine the headers of the file and return whether the file looks
- // like an ELF file for this architecture. Takes an already-open
- // file descriptor for the candidate file, reading in the prologue
- // to see if the ELF file appears to match the current
- // architecture. If error is non-NULL, it will be set with a reason
- // in case of failure.
- static bool IsArchElfFile(int fd, string *error) {
- unsigned char header[EI_NIDENT];
- if (pread(fd, header, sizeof(header), 0) != sizeof(header)) {
- if (error != NULL) *error = "Could not read header";
- return false;
- }
-
- if (memcmp(header, ELFMAG, SELFMAG) != 0) {
- if (error != NULL) *error = "Missing ELF magic";
- return false;
- }
-
- if (header[EI_CLASS] != ElfArch::kElfClass) {
- if (error != NULL) *error = "Different word size";
- return false;
- }
-
- int endian = 0;
- if (header[EI_DATA] == ELFDATA2LSB)
- endian = __LITTLE_ENDIAN;
- else if (header[EI_DATA] == ELFDATA2MSB)
- endian = __BIG_ENDIAN;
- if (endian != __BYTE_ORDER) {
- if (error != NULL) *error = "Different byte order";
- return false;
- }
-
- return true;
- }
-
- // Return true if we can use this symbol in Address-to-Symbol map.
- bool CanUseSymbol(const char *name, const typename ElfArch::Sym *sym) {
- // For now we only save FUNC and NOTYPE symbols. For now we just
- // care about functions, but some functions written in assembler
- // don't have a proper ELF type attached to them, so we store
- // NOTYPE symbols as well. The remaining significant type is
- // OBJECT (eg global variables), which represent about 25% of
- // the symbols in a typical google3 binary.
- if (ElfArch::Type(sym) != STT_FUNC &&
- ElfArch::Type(sym) != STT_NOTYPE) {
- return false;
- }
-
- // Target specific filtering.
- switch (header_.e_machine) {
- case EM_AARCH64:
- case EM_ARM:
- // Filter out '$x' special local symbols used by tools
- return name[0] != '$' || ElfArch::Bind(sym) != STB_LOCAL;
- case EM_X86_64:
- // Filter out read-only constants like .LC123.
- return name[0] != '.' || ElfArch::Bind(sym) != STB_LOCAL;
- default:
- return true;
- }
- }
-
- // Iterate over the symbols in a section, either SHT_DYNSYM or
- // SHT_SYMTAB. Add all symbols to the given SymbolMap.
- /*
- void GetSymbolPositions(SymbolMap *symbols,
- typename ElfArch::Word section_type,
- uint64 mem_offset,
- uint64 file_offset) {
- // This map is used to filter out "nested" functions.
- // See comment below.
- AddrToSymMap addr_to_sym_map;
- for (SymbolIterator<ElfArch> it(this, section_type);
- !it.done(); it.Next()) {
- const char *name = it.GetSymbolName();
- if (name == NULL)
- continue;
- const typename ElfArch::Sym *sym = it.GetSymbol();
- if (CanUseSymbol(name, sym)) {
- const int sec = sym->st_shndx;
-
- // We don't support special section indices. The most common
- // is SHN_ABS, for absolute symbols used deep in the bowels of
- // glibc. Also ignore any undefined symbols.
- if (sec == SHN_UNDEF ||
- (sec >= SHN_LORESERVE && sec <= SHN_HIRESERVE)) {
- continue;
- }
-
- const typename ElfArch::Shdr& hdr = section_headers_[sec];
-
- // Adjust for difference between where we expected to mmap
- // this section, and where it was actually mmapped.
- const int64 expected_base = hdr.sh_addr - hdr.sh_offset;
- const int64 real_base = mem_offset - file_offset;
- const int64 adjust = real_base - expected_base;
-
- uint64 start = sym->st_value + adjust;
-
- // Adjust function symbols for PowerPC64 by dereferencing and adjusting
- // the function descriptor to get the function address.
- if (header_.e_machine == EM_PPC64 && ElfArch::Type(sym) == STT_FUNC) {
- const uint64 opd_addr =
- AdjustPPC64FunctionDescriptorSymbolValue(sym->st_value);
- // Only adjust the returned value if the function address was found.
- if (opd_addr != sym->st_value) {
- const int64 adjust_function_symbols =
- real_base - base_for_text_;
- start = opd_addr + adjust_function_symbols;
- }
- }
-
- addr_to_sym_map.push_back(std::make_pair(start, sym));
- }
- }
- std::sort(addr_to_sym_map.begin(), addr_to_sym_map.end(), &AddrToSymSorter);
- addr_to_sym_map.erase(std::unique(addr_to_sym_map.begin(),
- addr_to_sym_map.end(), &AddrToSymEquals),
- addr_to_sym_map.end());
-
- // Squeeze out any "nested functions".
- // Nested functions are not allowed in C, but libc plays tricks.
- //
- // For example, here is disassembly of /lib64/tls/libc-2.3.5.so:
- // 0x00000000000aa380 <read+0>: cmpl $0x0,0x2781b9(%rip)
- // 0x00000000000aa387 <read+7>: jne 0xaa39b <read+27>
- // 0x00000000000aa389 <__read_nocancel+0>: mov $0x0,%rax
- // 0x00000000000aa390 <__read_nocancel+7>: syscall
- // 0x00000000000aa392 <__read_nocancel+9>: cmp $0xfffffffffffff001,%rax
- // 0x00000000000aa398 <__read_nocancel+15>: jae 0xaa3ef <read+111>
- // 0x00000000000aa39a <__read_nocancel+17>: retq
- // 0x00000000000aa39b <read+27>: sub $0x28,%rsp
- // 0x00000000000aa39f <read+31>: mov %rdi,0x8(%rsp)
- // ...
- // Without removing __read_nocancel, symbolizer will return NULL
- // given e.g. 0xaa39f (because the lower bound is __read_nocancel,
- // but 0xaa39f is beyond its end.
- if (addr_to_sym_map.empty()) {
- return;
- }
- const ElfSectionReader<ElfArch> *const symbol_section =
- this->GetSectionByType(section_type);
- const ElfSectionReader<ElfArch> *const string_section =
- this->GetSection(symbol_section->header().sh_link);
-
- typename AddrToSymMap::iterator curr = addr_to_sym_map.begin();
- // Always insert the first symbol.
- symbols->AddSymbol(string_section->GetOffset(curr->second->st_name),
- curr->first, curr->second->st_size);
- typename AddrToSymMap::iterator prev = curr++;
- for (; curr != addr_to_sym_map.end(); ++curr) {
- const uint64 prev_addr = prev->first;
- const uint64 curr_addr = curr->first;
- const typename ElfArch::Sym *const prev_sym = prev->second;
- const typename ElfArch::Sym *const curr_sym = curr->second;
- if (prev_addr + prev_sym->st_size <= curr_addr ||
- // The next condition is true if two symbols overlap like this:
- //
- // Previous symbol |----------------------------|
- // Current symbol |-------------------------------|
- //
- // These symbols are not found in google3 codebase, but in
- // jdk1.6.0_01_gg1/jre/lib/i386/server/libjvm.so.
- //
- // 0619e040 00000046 t CardTableModRefBS::write_region_work()
- // 0619e070 00000046 t CardTableModRefBS::write_ref_array_work()
- //
- // We allow overlapped symbols rather than ignore these.
- // Due to the way SymbolMap::GetSymbolAtPosition() works,
- // lookup for any address in [curr_addr, curr_addr + its size)
- // (e.g. 0619e071) will produce the current symbol,
- // which is the desired outcome.
- prev_addr + prev_sym->st_size < curr_addr + curr_sym->st_size) {
- const char *name = string_section->GetOffset(curr_sym->st_name);
- symbols->AddSymbol(name, curr_addr, curr_sym->st_size);
- prev = curr;
- } else {
- // Current symbol is "nested" inside previous one like this:
- //
- // Previous symbol |----------------------------|
- // Current symbol |---------------------|
- //
- // This happens within glibc, e.g. __read_nocancel is nested
- // "inside" __read. Ignore "inner" symbol.
- //DCHECK_LE(curr_addr + curr_sym->st_size,
- // prev_addr + prev_sym->st_size);
- ;
- }
- }
- }
-*/
-
- void VisitSymbols(typename ElfArch::Word section_type,
- ElfReader::SymbolSink *sink) {
- VisitSymbols(section_type, sink, -1, -1, false);
- }
-
- void VisitSymbols(typename ElfArch::Word section_type,
- ElfReader::SymbolSink *sink,
- int symbol_binding,
- int symbol_type,
- bool get_raw_symbol_values) {
- for (SymbolIterator<ElfArch> it(this, section_type);
- !it.done(); it.Next()) {
- const char *name = it.GetSymbolName();
- if (!name) continue;
- const typename ElfArch::Sym *sym = it.GetSymbol();
- if ((symbol_binding < 0 || ElfArch::Bind(sym) == symbol_binding) &&
- (symbol_type < 0 || ElfArch::Type(sym) == symbol_type)) {
- typename ElfArch::Sym symbol = *sym;
- // Add a PLT symbol in addition to the main undefined symbol.
- // Only do this for SHT_DYNSYM, because PLT symbols are dynamic.
- int symbol_index = it.GetCurrentSymbolIndex();
- // TODO(dthomson): Can be removed once all Java code is using the
- // Google3 launcher.
- if (section_type == SHT_DYNSYM &&
- static_cast<unsigned int>(symbol_index) < symbols_plt_offsets_.size() &&
- symbols_plt_offsets_[symbol_index] != 0) {
- string plt_name = string(name) + kPLTFunctionSuffix;
- if (plt_function_names_[symbol_index].empty()) {
- plt_function_names_[symbol_index] = plt_name;
- } else if (plt_function_names_[symbol_index] != plt_name) {
- ;
- }
- sink->AddSymbol(plt_function_names_[symbol_index].c_str(),
- symbols_plt_offsets_[it.GetCurrentSymbolIndex()],
- plt_code_size_);
- }
- if (!get_raw_symbol_values)
- AdjustSymbolValue(&symbol);
- sink->AddSymbol(name, symbol.st_value, symbol.st_size);
- }
- }
- }
-
- void VisitRelocationEntries() {
- if (visited_relocation_entries_) {
- return;
- }
- visited_relocation_entries_ = true;
-
- if (!plts_supported_) {
- return;
- }
- // First determine if PLTs exist. If not, then there is nothing to do.
- ElfReader::SectionInfo plt_section_info;
- const char* plt_section =
- GetSectionInfoByName(kElfPLTSectionName, &plt_section_info);
- if (!plt_section) {
- return;
- }
- if (plt_section_info.size == 0) {
- return;
- }
-
- // The PLTs could be referenced by either a Rel or Rela (Rel with Addend)
- // section.
- ElfReader::SectionInfo rel_section_info;
- ElfReader::SectionInfo rela_section_info;
- const char* rel_section =
- GetSectionInfoByName(kElfPLTRelSectionName, &rel_section_info);
- const char* rela_section =
- GetSectionInfoByName(kElfPLTRelaSectionName, &rela_section_info);
-
- const typename ElfArch::Rel* rel =
- reinterpret_cast<const typename ElfArch::Rel*>(rel_section);
- const typename ElfArch::Rela* rela =
- reinterpret_cast<const typename ElfArch::Rela*>(rela_section);
-
- if (!rel_section && !rela_section) {
- return;
- }
-
- // Use either Rel or Rela section, depending on which one exists.
- size_t section_size = rel_section ? rel_section_info.size
- : rela_section_info.size;
- size_t entry_size = rel_section ? sizeof(typename ElfArch::Rel)
- : sizeof(typename ElfArch::Rela);
-
- // Determine the number of entries in the dynamic symbol table.
- ElfReader::SectionInfo dynsym_section_info;
- const char* dynsym_section =
- GetSectionInfoByName(kElfDynSymSectionName, &dynsym_section_info);
- // The dynsym section might not exist, or it might be empty. In either case
- // there is nothing to be done so return.
- if (!dynsym_section || dynsym_section_info.size == 0) {
- return;
- }
- size_t num_dynamic_symbols =
- dynsym_section_info.size / dynsym_section_info.entsize;
- symbols_plt_offsets_.resize(num_dynamic_symbols, 0);
-
- // TODO(dthomson): Can be removed once all Java code is using the
- // Google3 launcher.
- // Make storage room for PLT function name strings.
- plt_function_names_.resize(num_dynamic_symbols);
-
- for (size_t i = 0; i < section_size / entry_size; ++i) {
- // Determine symbol index from the |r_info| field.
- int sym_index = ElfArch::r_sym(rel_section ? rel[i].r_info
- : rela[i].r_info);
- if (static_cast<unsigned int>(sym_index) >= symbols_plt_offsets_.size()) {
- continue;
- }
- symbols_plt_offsets_[sym_index] =
- plt_section_info.addr + plt0_size_ + i * plt_code_size_;
- }
- }
-
- // Return an ElfSectionReader for the first section of the given
- // type by iterating through all section headers. Returns NULL if
- // the section type is not found.
- const ElfSectionReader<ElfArch> *GetSectionByType(
- typename ElfArch::Word section_type) {
- for (unsigned int k = 0u; k < GetNumSections(); ++k) {
- if (section_headers_[k].sh_type == section_type) {
- return GetSection(k);
- }
- }
- return NULL;
- }
-
- // Return the name of section "shndx". Returns NULL if the section
- // is not found.
- const char *GetSectionNameByIndex(int shndx) {
- return GetSectionName(section_headers_[shndx].sh_name);
- }
-
- // Return a pointer to section "shndx", and store the size in
- // "size". Returns NULL if the section is not found.
- const char *GetSectionContentsByIndex(int shndx, size_t *size) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
- if (section != NULL) {
- *size = section->section_size();
- return section->contents();
- }
- return NULL;
- }
-
- // Return a pointer to the first section of the given name by
- // iterating through all section headers, and store the size in
- // "size". Returns NULL if the section name is not found.
- const char *GetSectionContentsByName(const string &section_name,
- size_t *size) {
- for (unsigned int k = 0u; k < GetNumSections(); ++k) {
- // When searching for sections in a .dwp file, the sections
- // we're looking for will always be at the end of the section
- // table, so reverse the direction of iteration.
- int shndx = is_dwp_ ? GetNumSections() - k - 1 : k;
- const char *name = GetSectionName(section_headers_[shndx].sh_name);
- if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
- if (section == NULL) {
- return NULL;
- } else {
- *size = section->section_size();
- return section->contents();
- }
- }
- }
- return NULL;
- }
-
- // This is like GetSectionContentsByName() but it returns a lot of extra
- // information about the section.
- const char *GetSectionInfoByName(const string &section_name,
- ElfReader::SectionInfo *info) {
- for (unsigned int k = 0u; k < GetNumSections(); ++k) {
- // When searching for sections in a .dwp file, the sections
- // we're looking for will always be at the end of the section
- // table, so reverse the direction of iteration.
- int shndx = is_dwp_ ? GetNumSections() - k - 1 : k;
- const char *name = GetSectionName(section_headers_[shndx].sh_name);
- if (name != NULL && ElfReader::SectionNamesMatch(section_name, name)) {
- const ElfSectionReader<ElfArch> *section = GetSection(shndx);
- if (section == NULL) {
- return NULL;
- } else {
- info->type = section->header().sh_type;
- info->flags = section->header().sh_flags;
- info->addr = section->header().sh_addr;
- info->offset = section->header().sh_offset;
- info->size = section->header().sh_size;
- info->link = section->header().sh_link;
- info->info = section->header().sh_info;
- info->addralign = section->header().sh_addralign;
- info->entsize = section->header().sh_entsize;
- return section->contents();
- }
- }
- }
- return NULL;
- }
-
- // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
- // segments are present. This is the address an ELF image was linked
- // (by static linker) to be loaded at. Usually (but not always) 0 for
- // shared libraries and position-independent executables.
- uint64 VaddrOfFirstLoadSegment() const {
- // Relocatable objects (of type ET_REL) do not have LOAD segments.
- if (header_.e_type == ET_REL) {
- return 0;
- }
- for (int i = 0; i < GetNumProgramHeaders(); ++i) {
- if (program_headers_[i].p_type == PT_LOAD) {
- return program_headers_[i].p_vaddr;
- }
- }
- return 0;
- }
-
- // According to the LSB ("ELF special sections"), sections with debug
- // info are prefixed by ".debug". The names are not specified, but they
- // look like ".debug_line", ".debug_info", etc.
- bool HasDebugSections() {
- // Debug sections are likely to be near the end, so reverse the
- // direction of iteration.
- for (int k = GetNumSections() - 1; k >= 0; --k) {
- const char *name = GetSectionName(section_headers_[k].sh_name);
- if (strncmp(name, ".debug", strlen(".debug")) == 0) return true;
- if (strncmp(name, ".zdebug", strlen(".zdebug")) == 0) return true;
- }
- return false;
- }
-
- bool IsDynamicSharedObject() const {
- return header_.e_type == ET_DYN;
- }
-
- // Return the number of sections.
- uint64_t GetNumSections() const {
- if (HasManySections())
- return first_section_header_.sh_size;
- return header_.e_shnum;
- }
-
- private:
- typedef vector<pair<uint64, const typename ElfArch::Sym *> > AddrToSymMap;
-
- static bool AddrToSymSorter(const typename AddrToSymMap::value_type& lhs,
- const typename AddrToSymMap::value_type& rhs) {
- return lhs.first < rhs.first;
- }
-
- static bool AddrToSymEquals(const typename AddrToSymMap::value_type& lhs,
- const typename AddrToSymMap::value_type& rhs) {
- return lhs.first == rhs.first;
- }
-
- // Does this ELF file have too many sections to fit in the program header?
- bool HasManySections() const {
- return header_.e_shnum == SHN_UNDEF;
- }
-
- // Return the number of program headers.
- int GetNumProgramHeaders() const {
- if (HasManySections() && header_.e_phnum == 0xffff &&
- first_section_header_.sh_info != 0)
- return first_section_header_.sh_info;
- return header_.e_phnum;
- }
-
- // Return the index of the string table.
- int GetStringTableIndex() const {
- if (HasManySections()) {
- if (header_.e_shstrndx == 0xffff)
- return first_section_header_.sh_link;
- else if (header_.e_shstrndx >= GetNumSections())
- return 0;
- }
- return header_.e_shstrndx;
- }
-
- // Given an offset into the section header string table, return the
- // section name.
- const char *GetSectionName(typename ElfArch::Word sh_name) {
- const ElfSectionReader<ElfArch> *shstrtab =
- GetSection(GetStringTableIndex());
- if (shstrtab != NULL) {
- return shstrtab->GetOffset(sh_name);
- }
- return NULL;
- }
-
- // Return an ElfSectionReader for the given section. The reader will
- // be freed when this object is destroyed.
- const ElfSectionReader<ElfArch> *GetSection(int num) {
- const char *name;
- // Hard-coding the name for the section-name string table prevents
- // infinite recursion.
- if (num == GetStringTableIndex())
- name = ".shstrtab";
- else
- name = GetSectionNameByIndex(num);
- ElfSectionReader<ElfArch> *& reader = sections_[num];
- if (reader == NULL)
- reader = new ElfSectionReader<ElfArch>(name, path_, fd_,
- section_headers_[num]);
- return reader;
- }
-
- // Parse out the overall header information from the file and assert
- // that it looks sane. This contains information like the magic
- // number and target architecture.
- bool ParseHeaders(int fd, const string &path) {
- // Read in the global ELF header.
- if (pread(fd, &header_, sizeof(header_), 0) != sizeof(header_)) {
- return false;
- }
-
- // Must be an executable, dynamic shared object or relocatable object
- if (header_.e_type != ET_EXEC &&
- header_.e_type != ET_DYN &&
- header_.e_type != ET_REL) {
- return false;
- }
- // Need a section header.
- if (header_.e_shoff == 0) {
- return false;
- }
-
- if (header_.e_shnum == SHN_UNDEF) {
- // The number of sections in the program header is only a 16-bit value. In
- // the event of overflow (greater than SHN_LORESERVE sections), e_shnum
- // will read SHN_UNDEF and the true number of section header table entries
- // is found in the sh_size field of the first section header.
- // See: http://www.sco.com/developers/gabi/2003-12-17/ch4.sheader.html
- if (pread(fd, &first_section_header_, sizeof(first_section_header_),
- header_.e_shoff) != sizeof(first_section_header_)) {
- return false;
- }
- }
-
- // Dynamically allocate enough space to store the section headers
- // and read them out of the file.
- const int section_headers_size =
- GetNumSections() * sizeof(*section_headers_);
- section_headers_ = new typename ElfArch::Shdr[section_headers_size];
- if (pread(fd, section_headers_, section_headers_size, header_.e_shoff) !=
- section_headers_size) {
- return false;
- }
-
- // Dynamically allocate enough space to store the program headers
- // and read them out of the file.
- //const int program_headers_size =
- // GetNumProgramHeaders() * sizeof(*program_headers_);
- program_headers_ = new typename ElfArch::Phdr[GetNumProgramHeaders()];
-
- // Presize the sections array for efficiency.
- sections_.resize(GetNumSections(), NULL);
- return true;
- }
-
- // Given the "value" of a function descriptor return the address of the
- // function (i.e. the dereferenced value). Otherwise return "value".
- uint64 AdjustPPC64FunctionDescriptorSymbolValue(uint64 value) {
- if (opd_section_ != NULL &&
- opd_info_.addr <= value &&
- value < opd_info_.addr + opd_info_.size) {
- uint64 offset = value - opd_info_.addr;
- return (*reinterpret_cast<const uint64*>(opd_section_ + offset));
- }
- return value;
- }
-
- void AdjustSymbolValue(typename ElfArch::Sym* sym) {
- switch (header_.e_machine) {
- case EM_ARM:
- // For ARM architecture, if the LSB of the function symbol offset is set,
- // it indicates a Thumb function. This bit should not be taken literally.
- // Clear it.
- if (ElfArch::Type(sym) == STT_FUNC)
- sym->st_value = AdjustARMThumbSymbolValue(sym->st_value);
- break;
- case EM_386:
- // No adjustment needed for Intel x86 architecture. However, explicitly
- // define this case as we use it quite often.
- break;
- case EM_PPC64:
- // PowerPC64 currently has function descriptors as part of the ABI.
- // Function symbols need to be adjusted accordingly.
- if (ElfArch::Type(sym) == STT_FUNC)
- sym->st_value = AdjustPPC64FunctionDescriptorSymbolValue(sym->st_value);
- break;
- default:
- break;
- }
- }
-
- friend class SymbolIterator<ElfArch>;
-
- // The file we're reading.
- const string path_;
- // Open file descriptor for path_. Not owned by this object.
- const int fd_;
-
- // The global header of the ELF file.
- typename ElfArch::Ehdr header_;
-
- // The header of the first section. This may be used to supplement the ELF
- // file header.
- typename ElfArch::Shdr first_section_header_;
-
- // Array of GetNumSections() section headers, allocated when we read
- // in the global header.
- typename ElfArch::Shdr *section_headers_;
-
- // Array of GetNumProgramHeaders() program headers, allocated when we read
- // in the global header.
- typename ElfArch::Phdr *program_headers_;
-
- // An array of pointers to ElfSectionReaders. Sections are
- // mmaped as they're needed and not released until this object is
- // destroyed.
- vector<ElfSectionReader<ElfArch>*> sections_;
-
- // For PowerPC64 we need to keep track of function descriptors when looking up
- // values for funtion symbols values. Function descriptors are kept in the
- // .opd section and are dereferenced to find the function address.
- ElfReader::SectionInfo opd_info_;
- const char *opd_section_; // Must be checked for NULL before use.
- int64 base_for_text_;
-
- // Read PLT-related sections for the current architecture.
- bool plts_supported_;
- // Code size of each PLT function for the current architecture.
- size_t plt_code_size_;
- // Size of the special first entry in the .plt section that calls the runtime
- // loader resolution routine, and that all other entries jump to when doing
- // lazy symbol binding.
- size_t plt0_size_;
-
- // Maps a dynamic symbol index to a PLT offset.
- // The vector entry index is the dynamic symbol index.
- std::vector<uint64> symbols_plt_offsets_;
-
- // Container for PLT function name strings. These strings are passed by
- // reference to SymbolSink::AddSymbol() so they need to be stored somewhere.
- std::vector<string> plt_function_names_;
-
- bool visited_relocation_entries_;
-
- // True if this is a .dwp file.
- bool is_dwp_;
-};
-
-ElfReader::ElfReader(const string &path)
- : path_(path), fd_(-1), impl32_(NULL), impl64_(NULL) {
- // linux 2.6.XX kernel can show deleted files like this:
- // /var/run/nscd/dbYLJYaE (deleted)
- // and the kernel-supplied vdso and vsyscall mappings like this:
- // [vdso]
- // [vsyscall]
- if (MyHasSuffixString(path, " (deleted)"))
- return;
- if (path == "[vdso]")
- return;
- if (path == "[vsyscall]")
- return;
-
- fd_ = open(path.c_str(), O_RDONLY);
-}
-
-ElfReader::~ElfReader() {
- if (fd_ != -1)
- close(fd_);
- if (impl32_ != NULL)
- delete impl32_;
- if (impl64_ != NULL)
- delete impl64_;
-}
-
-
-// The only word-size specific part of this file is IsNativeElfFile().
-#if __WORDSIZE == 32
-#define NATIVE_ELF_ARCH Elf32
-#elif __WORDSIZE == 64
-#define NATIVE_ELF_ARCH Elf64
-#else
-#error "Invalid word size"
-#endif
-
-template <typename ElfArch>
-static bool IsElfFile(const int fd, const string &path) {
- if (fd < 0)
- return false;
- if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) {
- // No error message here. IsElfFile gets called many times.
- return false;
- }
- return true;
-}
-
-bool ElfReader::IsNativeElfFile() const {
- return IsElfFile<NATIVE_ELF_ARCH>(fd_, path_);
-}
-
-bool ElfReader::IsElf32File() const {
- return IsElfFile<Elf32>(fd_, path_);
-}
-
-bool ElfReader::IsElf64File() const {
- return IsElfFile<Elf64>(fd_, path_);
-}
-
-/*
-void ElfReader::AddSymbols(SymbolMap *symbols,
- uint64 mem_offset, uint64 file_offset,
- uint64 length) {
- if (fd_ < 0)
- return;
- // TODO(chatham): Actually use the information about file offset and
- // the length of the mapped section. On some machines the data
- // section gets mapped as executable, and we'll end up reading the
- // file twice and getting some of the offsets wrong.
- if (IsElf32File()) {
- GetImpl32()->GetSymbolPositions(symbols, SHT_SYMTAB,
- mem_offset, file_offset);
- GetImpl32()->GetSymbolPositions(symbols, SHT_DYNSYM,
- mem_offset, file_offset);
- } else if (IsElf64File()) {
- GetImpl64()->GetSymbolPositions(symbols, SHT_SYMTAB,
- mem_offset, file_offset);
- GetImpl64()->GetSymbolPositions(symbols, SHT_DYNSYM,
- mem_offset, file_offset);
- }
-}
-*/
-
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink) {
- VisitSymbols(sink, -1, -1);
-}
-
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink,
- int symbol_binding,
- int symbol_type) {
- VisitSymbols(sink, symbol_binding, symbol_type, false);
-}
-
-void ElfReader::VisitSymbols(ElfReader::SymbolSink *sink,
- int symbol_binding,
- int symbol_type,
- bool get_raw_symbol_values) {
- if (IsElf32File()) {
- GetImpl32()->VisitRelocationEntries();
- GetImpl32()->VisitSymbols(SHT_SYMTAB, sink, symbol_binding, symbol_type,
- get_raw_symbol_values);
- GetImpl32()->VisitSymbols(SHT_DYNSYM, sink, symbol_binding, symbol_type,
- get_raw_symbol_values);
- } else if (IsElf64File()) {
- GetImpl64()->VisitRelocationEntries();
- GetImpl64()->VisitSymbols(SHT_SYMTAB, sink, symbol_binding, symbol_type,
- get_raw_symbol_values);
- GetImpl64()->VisitSymbols(SHT_DYNSYM, sink, symbol_binding, symbol_type,
- get_raw_symbol_values);
- }
-}
-
-uint64 ElfReader::VaddrOfFirstLoadSegment() {
- if (IsElf32File()) {
- return GetImpl32()->VaddrOfFirstLoadSegment();
- } else if (IsElf64File()) {
- return GetImpl64()->VaddrOfFirstLoadSegment();
- } else {
- return 0;
- }
-}
-
-const char *ElfReader::GetSectionName(int shndx) {
- if (shndx < 0 || static_cast<unsigned int>(shndx) >= GetNumSections()) return NULL;
- if (IsElf32File()) {
- return GetImpl32()->GetSectionNameByIndex(shndx);
- } else if (IsElf64File()) {
- return GetImpl64()->GetSectionNameByIndex(shndx);
- } else {
- return NULL;
- }
-}
-
-uint64 ElfReader::GetNumSections() {
- if (IsElf32File()) {
- return GetImpl32()->GetNumSections();
- } else if (IsElf64File()) {
- return GetImpl64()->GetNumSections();
- } else {
- return 0;
- }
-}
-
-const char *ElfReader::GetSectionByIndex(int shndx, size_t *size) {
- if (IsElf32File()) {
- return GetImpl32()->GetSectionContentsByIndex(shndx, size);
- } else if (IsElf64File()) {
- return GetImpl64()->GetSectionContentsByIndex(shndx, size);
- } else {
- return NULL;
- }
-}
-
-const char *ElfReader::GetSectionByName(const string &section_name,
- size_t *size) {
- if (IsElf32File()) {
- return GetImpl32()->GetSectionContentsByName(section_name, size);
- } else if (IsElf64File()) {
- return GetImpl64()->GetSectionContentsByName(section_name, size);
- } else {
- return NULL;
- }
-}
-
-const char *ElfReader::GetSectionInfoByName(const string &section_name,
- SectionInfo *info) {
- if (IsElf32File()) {
- return GetImpl32()->GetSectionInfoByName(section_name, info);
- } else if (IsElf64File()) {
- return GetImpl64()->GetSectionInfoByName(section_name, info);
- } else {
- return NULL;
- }
-}
-
-bool ElfReader::SectionNamesMatch(const string &name, const string &sh_name) {
- if ((name.find(".debug_", 0) == 0) && (sh_name.find(".zdebug_", 0) == 0)) {
- const string name_suffix(name, strlen(".debug_"));
- const string sh_name_suffix(sh_name, strlen(".zdebug_"));
- return name_suffix == sh_name_suffix;
- }
- return name == sh_name;
-}
-
-bool ElfReader::IsDynamicSharedObject() {
- if (IsElf32File()) {
- return GetImpl32()->IsDynamicSharedObject();
- } else if (IsElf64File()) {
- return GetImpl64()->IsDynamicSharedObject();
- } else {
- return false;
- }
-}
-
-ElfReaderImpl<Elf32> *ElfReader::GetImpl32() {
- if (impl32_ == NULL) {
- impl32_ = new ElfReaderImpl<Elf32>(path_, fd_);
- }
- return impl32_;
-}
-
-ElfReaderImpl<Elf64> *ElfReader::GetImpl64() {
- if (impl64_ == NULL) {
- impl64_ = new ElfReaderImpl<Elf64>(path_, fd_);
- }
- return impl64_;
-}
-
-// Return true if file is an ELF binary of ElfArch, with unstripped
-// debug info (debug_only=true) or symbol table (debug_only=false).
-// Otherwise, return false.
-template <typename ElfArch>
-static bool IsNonStrippedELFBinaryImpl(const string &path, const int fd,
- bool debug_only) {
- if (!ElfReaderImpl<ElfArch>::IsArchElfFile(fd, NULL)) return false;
- ElfReaderImpl<ElfArch> elf_reader(path, fd);
- return debug_only ?
- elf_reader.HasDebugSections()
- : (elf_reader.GetSectionByType(SHT_SYMTAB) != NULL);
-}
-
-// Helper for the IsNon[Debug]StrippedELFBinary functions.
-static bool IsNonStrippedELFBinaryHelper(const string &path,
- bool debug_only) {
- const int fd = open(path.c_str(), O_RDONLY);
- if (fd == -1) {
- return false;
- }
-
- if (IsNonStrippedELFBinaryImpl<Elf32>(path, fd, debug_only) ||
- IsNonStrippedELFBinaryImpl<Elf64>(path, fd, debug_only)) {
- close(fd);
- return true;
- }
- close(fd);
- return false;
-}
-
-bool ElfReader::IsNonStrippedELFBinary(const string &path) {
- return IsNonStrippedELFBinaryHelper(path, false);
-}
-
-bool ElfReader::IsNonDebugStrippedELFBinary(const string &path) {
- return IsNonStrippedELFBinaryHelper(path, true);
-}
-} // namespace dwarf2reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h
deleted file mode 100644
index 07477341f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/elf_reader.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2005 Google Inc. All Rights Reserved.
-// Author: chatham@google.com (Andrew Chatham)
-// Author: satorux@google.com (Satoru Takabayashi)
-//
-// ElfReader handles reading in ELF. It can extract symbols from the
-// current process, which may be used to symbolize stack traces
-// without having to make a potentially dangerous call to fork().
-//
-// ElfReader dynamically allocates memory, so it is not appropriate to
-// use once the address space might be corrupted, such as during
-// process death.
-//
-// ElfReader supports both 32-bit and 64-bit ELF binaries.
-
-#ifndef COMMON_DWARF_ELF_READER_H__
-#define COMMON_DWARF_ELF_READER_H__
-
-#include <string>
-#include <vector>
-
-#include "common/dwarf/types.h"
-
-using std::string;
-using std::vector;
-using std::pair;
-
-namespace dwarf2reader {
-
-class SymbolMap;
-class Elf32;
-class Elf64;
-template<typename ElfArch>
-class ElfReaderImpl;
-
-class ElfReader {
- public:
- explicit ElfReader(const string &path);
- ~ElfReader();
-
- // Parse the ELF prologue of this file and return whether it was
- // successfully parsed and matches the word size and byte order of
- // the current process.
- bool IsNativeElfFile() const;
-
- // Similar to IsNativeElfFile but checks if it's a 32-bit ELF file.
- bool IsElf32File() const;
-
- // Similar to IsNativeElfFile but checks if it's a 64-bit ELF file.
- bool IsElf64File() const;
-
- // Checks if it's an ELF file of type ET_DYN (shared object file).
- bool IsDynamicSharedObject();
-
- // Add symbols in the given ELF file into the provided SymbolMap,
- // assuming that the file has been loaded into the specified
- // offset.
- //
- // The remaining arguments are typically taken from a
- // ProcMapsIterator (base/sysinfo.h) and describe which portions of
- // the ELF file are mapped into which parts of memory:
- //
- // mem_offset - position at which the segment is mapped into memory
- // file_offset - offset in the file where the mapping begins
- // length - length of the mapped segment
- void AddSymbols(SymbolMap *symbols,
- uint64 mem_offset, uint64 file_offset,
- uint64 length);
-
- class SymbolSink {
- public:
- virtual ~SymbolSink() {}
- virtual void AddSymbol(const char *name, uint64 address, uint64 size) = 0;
- };
-
- // Like AddSymbols above, but with no address correction.
- // Processes any SHT_SYMTAB section, followed by any SHT_DYNSYM section.
- void VisitSymbols(SymbolSink *sink);
-
- // Like VisitSymbols above, but for a specific symbol binding/type.
- // A negative value for the binding and type parameters means any
- // binding or type.
- void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type);
-
- // Like VisitSymbols above but can optionally export raw symbol values instead
- // of adjusted ones.
- void VisitSymbols(SymbolSink *sink, int symbol_binding, int symbol_type,
- bool get_raw_symbol_values);
-
- // p_vaddr of the first PT_LOAD segment (if any), or 0 if no PT_LOAD
- // segments are present. This is the address an ELF image was linked
- // (by static linker) to be loaded at. Usually (but not always) 0 for
- // shared libraries and position-independent executables.
- uint64 VaddrOfFirstLoadSegment();
-
- // Return the name of section "shndx". Returns NULL if the section
- // is not found.
- const char *GetSectionName(int shndx);
-
- // Return the number of sections in the given ELF file.
- uint64 GetNumSections();
-
- // Get section "shndx" from the given ELF file. On success, return
- // the pointer to the section and store the size in "size".
- // On error, return NULL. The returned section data is only valid
- // until the ElfReader gets destroyed.
- const char *GetSectionByIndex(int shndx, size_t *size);
-
- // Get section with "section_name" (ex. ".text", ".symtab") in the
- // given ELF file. On success, return the pointer to the section
- // and store the size in "size". On error, return NULL. The
- // returned section data is only valid until the ElfReader gets
- // destroyed.
- const char *GetSectionByName(const string &section_name, size_t *size);
-
- // This is like GetSectionByName() but it returns a lot of extra information
- // about the section. The SectionInfo structure is almost identical to
- // the typedef struct Elf64_Shdr defined in <elf.h>, but is redefined
- // here so that the many short macro names in <elf.h> don't have to be
- // added to our already cluttered namespace.
- struct SectionInfo {
- uint32 type; // Section type (SHT_xxx constant from elf.h).
- uint64 flags; // Section flags (SHF_xxx constants from elf.h).
- uint64 addr; // Section virtual address at execution.
- uint64 offset; // Section file offset.
- uint64 size; // Section size in bytes.
- uint32 link; // Link to another section.
- uint32 info; // Additional section information.
- uint64 addralign; // Section alignment.
- uint64 entsize; // Entry size if section holds a table.
- };
- const char *GetSectionInfoByName(const string &section_name,
- SectionInfo *info);
-
- // Check if "path" is an ELF binary that has not been stripped of symbol
- // tables. This function supports both 32-bit and 64-bit ELF binaries.
- static bool IsNonStrippedELFBinary(const string &path);
-
- // Check if "path" is an ELF binary that has not been stripped of debug
- // info. Unlike IsNonStrippedELFBinary, this function will return
- // false for binaries passed through "strip -S".
- static bool IsNonDebugStrippedELFBinary(const string &path);
-
- // Match a requested section name with the section name as it
- // appears in the elf-file, adjusting for compressed debug section
- // names. For example, returns true if name == ".debug_abbrev" and
- // sh_name == ".zdebug_abbrev"
- static bool SectionNamesMatch(const string &name, const string &sh_name);
-
- private:
- // Lazily initialize impl32_ and return it.
- ElfReaderImpl<Elf32> *GetImpl32();
- // Ditto for impl64_.
- ElfReaderImpl<Elf64> *GetImpl64();
-
- // Path of the file we're reading.
- const string path_;
- // Read-only file descriptor for the file. May be -1 if there was an
- // error during open.
- int fd_;
- ElfReaderImpl<Elf32> *impl32_;
- ElfReaderImpl<Elf64> *impl64_;
-};
-
-} // namespace dwarf2reader
-
-#endif // COMMON_DWARF_ELF_READER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc
deleted file mode 100644
index 55a255eda..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// 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.
-
-// This is a client for the dwarf2reader to extract function and line
-// information from the debug info.
-
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include <map>
-#include <queue>
-#include <vector>
-
-#include "common/dwarf/functioninfo.h"
-#include "common/dwarf/bytereader.h"
-#include "common/scoped_ptr.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::scoped_ptr;
-
-namespace dwarf2reader {
-
-CULineInfoHandler::CULineInfoHandler(std::vector<SourceFileInfo>* files,
- std::vector<string>* dirs,
- LineMap* linemap):linemap_(linemap),
- files_(files),
- dirs_(dirs) {
- // The dirs and files are 1 indexed, so just make sure we put
- // nothing in the 0 vector.
- assert(dirs->size() == 0);
- assert(files->size() == 0);
- dirs->push_back("");
- SourceFileInfo s;
- s.name = "";
- s.lowpc = ULLONG_MAX;
- files->push_back(s);
-}
-
-void CULineInfoHandler::DefineDir(const string& name, uint32 dir_num) {
- // These should never come out of order, actually
- assert(dir_num == dirs_->size());
- dirs_->push_back(name);
-}
-
-void CULineInfoHandler::DefineFile(const string& name,
- int32 file_num, uint32 dir_num,
- uint64 mod_time, uint64 length) {
- assert(dir_num >= 0);
- assert(dir_num < dirs_->size());
-
- // These should never come out of order, actually.
- if (file_num == (int32)files_->size() || file_num == -1) {
- string dir = dirs_->at(dir_num);
-
- SourceFileInfo s;
- s.lowpc = ULLONG_MAX;
-
- if (dir == "") {
- s.name = name;
- } else {
- s.name = dir + "/" + name;
- }
-
- files_->push_back(s);
- } else {
- fprintf(stderr, "error in DefineFile");
- }
-}
-
-void CULineInfoHandler::AddLine(uint64 address, uint64 length, uint32 file_num,
- uint32 line_num, uint32 column_num) {
- if (file_num < files_->size()) {
- linemap_->insert(
- std::make_pair(address,
- std::make_pair(files_->at(file_num).name.c_str(),
- line_num)));
-
- if (address < files_->at(file_num).lowpc) {
- files_->at(file_num).lowpc = address;
- }
- } else {
- fprintf(stderr, "error in AddLine");
- }
-}
-
-bool CUFunctionInfoHandler::StartCompilationUnit(uint64 offset,
- uint8 address_size,
- uint8 offset_size,
- uint64 cu_length,
- uint8 dwarf_version) {
- current_compilation_unit_offset_ = offset;
- return true;
-}
-
-
-// For function info, we only care about subprograms and inlined
-// subroutines. For line info, the DW_AT_stmt_list lives in the
-// compile unit tag.
-
-bool CUFunctionInfoHandler::StartDIE(uint64 offset, enum DwarfTag tag) {
- switch (tag) {
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine: {
- current_function_info_ = new FunctionInfo;
- current_function_info_->lowpc = current_function_info_->highpc = 0;
- current_function_info_->name = "";
- current_function_info_->line = 0;
- current_function_info_->file = "";
- offset_to_funcinfo_->insert(std::make_pair(offset,
- current_function_info_));
- };
- // FALLTHROUGH
- case DW_TAG_compile_unit:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-// Only care about the name attribute for functions
-
-void CUFunctionInfoHandler::ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data) {
- if (current_function_info_) {
- if (attr == DW_AT_name)
- current_function_info_->name = data;
- else if (attr == DW_AT_MIPS_linkage_name)
- current_function_info_->mangled_name = data;
- }
-}
-
-void CUFunctionInfoHandler::ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- if (attr == DW_AT_stmt_list) {
- SectionMap::const_iterator iter = sections_.find("__debug_line");
- assert(iter != sections_.end());
-
- scoped_ptr<LineInfo> lireader(new LineInfo(iter->second.first + data,
- iter->second.second - data,
- reader_, linehandler_));
- lireader->Start();
- } else if (current_function_info_) {
- switch (attr) {
- case DW_AT_low_pc:
- current_function_info_->lowpc = data;
- break;
- case DW_AT_high_pc:
- current_function_info_->highpc = data;
- break;
- case DW_AT_decl_line:
- current_function_info_->line = data;
- break;
- case DW_AT_decl_file:
- current_function_info_->file = files_->at(data).name;
- break;
- default:
- break;
- }
- }
-}
-
-void CUFunctionInfoHandler::ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- if (current_function_info_) {
- switch (attr) {
- case DW_AT_specification: {
- // Some functions have a "specification" attribute
- // which means they were defined elsewhere. The name
- // attribute is not repeated, and must be taken from
- // the specification DIE. Here we'll assume that
- // any DIE referenced in this manner will already have
- // been seen, but that's not really required by the spec.
- FunctionMap::iterator iter = offset_to_funcinfo_->find(data);
- if (iter != offset_to_funcinfo_->end()) {
- current_function_info_->name = iter->second->name;
- current_function_info_->mangled_name = iter->second->mangled_name;
- } else {
- // If you hit this, this code probably needs to be rewritten.
- fprintf(stderr,
- "Error: DW_AT_specification was seen before the referenced "
- "DIE! (Looking for DIE at offset %08llx, in DIE at "
- "offset %08llx)\n", data, offset);
- }
- break;
- }
- default:
- break;
- }
- }
-}
-
-void CUFunctionInfoHandler::EndDIE(uint64 offset) {
- if (current_function_info_ && current_function_info_->lowpc)
- address_to_funcinfo_->insert(std::make_pair(current_function_info_->lowpc,
- current_function_info_));
-}
-
-} // namespace dwarf2reader
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h
deleted file mode 100644
index 0b08a5fc5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/functioninfo.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// 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.
-
-
-// This file contains the definitions for a DWARF2/3 information
-// collector that uses the DWARF2/3 reader interface to build a mapping
-// of addresses to files, lines, and functions.
-
-#ifndef COMMON_DWARF_FUNCTIONINFO_H__
-#define COMMON_DWARF_FUNCTIONINFO_H__
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-
-
-namespace dwarf2reader {
-
-struct FunctionInfo {
- // Name of the function
- string name;
- // Mangled name of the function
- string mangled_name;
- // File containing this function
- string file;
- // Line number for start of function.
- uint32 line;
- // Beginning address for this function
- uint64 lowpc;
- // End address for this function.
- uint64 highpc;
-};
-
-struct SourceFileInfo {
- // Name of the source file name
- string name;
- // Low address of source file name
- uint64 lowpc;
-};
-
-typedef std::map<uint64, FunctionInfo*> FunctionMap;
-typedef std::map<uint64, std::pair<string, uint32> > LineMap;
-
-// This class is a basic line info handler that fills in the dirs,
-// file, and linemap passed into it with the data produced from the
-// LineInfoHandler.
-class CULineInfoHandler: public LineInfoHandler {
- public:
-
- //
- CULineInfoHandler(std::vector<SourceFileInfo>* files,
- std::vector<string>* dirs,
- LineMap* linemap);
- virtual ~CULineInfoHandler() { }
-
- // Called when we define a directory. We just place NAME into dirs_
- // at position DIR_NUM.
- virtual void DefineDir(const string& name, uint32 dir_num);
-
- // Called when we define a filename. We just place
- // concat(dirs_[DIR_NUM], NAME) into files_ at position FILE_NUM.
- virtual void DefineFile(const string& name, int32 file_num,
- uint32 dir_num, uint64 mod_time, uint64 length);
-
-
- // Called when the line info reader has a new line, address pair
- // ready for us. ADDRESS is the address of the code, LENGTH is the
- // length of its machine code in bytes, FILE_NUM is the file number
- // containing the code, LINE_NUM is the line number in that file for
- // the code, and COLUMN_NUM is the column number the code starts at,
- // if we know it (0 otherwise).
- virtual void AddLine(uint64 address, uint64 length,
- uint32 file_num, uint32 line_num, uint32 column_num);
-
- private:
- LineMap* linemap_;
- std::vector<SourceFileInfo>* files_;
- std::vector<string>* dirs_;
-};
-
-class CUFunctionInfoHandler: public Dwarf2Handler {
- public:
- CUFunctionInfoHandler(std::vector<SourceFileInfo>* files,
- std::vector<string>* dirs,
- LineMap* linemap,
- FunctionMap* offset_to_funcinfo,
- FunctionMap* address_to_funcinfo,
- CULineInfoHandler* linehandler,
- const SectionMap& sections,
- ByteReader* reader)
- : files_(files), dirs_(dirs), linemap_(linemap),
- offset_to_funcinfo_(offset_to_funcinfo),
- address_to_funcinfo_(address_to_funcinfo),
- linehandler_(linehandler), sections_(sections),
- reader_(reader), current_function_info_(NULL) { }
-
- virtual ~CUFunctionInfoHandler() { }
-
- // Start to process a compilation unit at OFFSET from the beginning of the
- // .debug_info section. We want to see all compilation units, so we
- // always return true.
-
- virtual bool StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version);
-
- // Start to process a DIE at OFFSET from the beginning of the
- // .debug_info section. We only care about function related DIE's.
- virtual bool StartDIE(uint64 offset, enum DwarfTag tag);
-
- // Called when we have an attribute with unsigned data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of the .debug_info section, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA.
- virtual void ProcessAttributeUnsigned(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
-
- // Called when we have an attribute with a DIE reference to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of the .debug_info section, has a name of ATTR, a form of
- // FORM, and the offset of the referenced DIE from the start of the
- // .debug_info section is in DATA.
- virtual void ProcessAttributeReference(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
-
- // Called when we have an attribute with string data to give to
- // our handler. The attribute is for the DIE at OFFSET from the
- // beginning of the .debug_info section, has a name of ATTR, a form of
- // FORM, and the actual data of the attribute is in DATA.
- virtual void ProcessAttributeString(uint64 offset,
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string& data);
-
- // Called when finished processing the DIE at OFFSET.
- // Because DWARF2/3 specifies a tree of DIEs, you may get starts
- // before ends of the previous DIE, as we process children before
- // ending the parent.
- virtual void EndDIE(uint64 offset);
-
- private:
- std::vector<SourceFileInfo>* files_;
- std::vector<string>* dirs_;
- LineMap* linemap_;
- FunctionMap* offset_to_funcinfo_;
- FunctionMap* address_to_funcinfo_;
- CULineInfoHandler* linehandler_;
- const SectionMap& sections_;
- ByteReader* reader_;
- FunctionInfo* current_function_info_;
- uint64 current_compilation_unit_offset_;
-};
-
-} // namespace dwarf2reader
-#endif // COMMON_DWARF_FUNCTIONINFO_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h
deleted file mode 100644
index 0ff72abcf..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/line_state_machine.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 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.
-
-
-#ifndef COMMON_DWARF_LINE_STATE_MACHINE_H__
-#define COMMON_DWARF_LINE_STATE_MACHINE_H__
-
-namespace dwarf2reader {
-
-// This is the format of a DWARF2/3 line state machine that we process
-// opcodes using. There is no need for anything outside the lineinfo
-// processor to know how this works.
-struct LineStateMachine {
- void Reset(bool default_is_stmt) {
- file_num = 1;
- address = 0;
- line_num = 1;
- column_num = 0;
- is_stmt = default_is_stmt;
- basic_block = false;
- end_sequence = false;
- }
-
- uint32 file_num;
- uint64 address;
- uint32 line_num;
- uint32 column_num;
- bool is_stmt; // stmt means statement.
- bool basic_block;
- bool end_sequence;
-};
-
-} // namespace dwarf2reader
-
-
-#endif // COMMON_DWARF_LINE_STATE_MACHINE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/moz.build b/toolkit/crashreporter/google-breakpad/src/common/dwarf/moz.build
deleted file mode 100644
index e1ccc65ac..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/moz.build
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-HostLibrary('host_breakpad_dwarf_s')
-HOST_SOURCES += [
- 'bytereader.cc',
- 'dwarf2diehandler.cc',
- 'dwarf2reader.cc',
- 'elf_reader.cc',
- 'functioninfo.cc',
-]
-HOST_CXXFLAGS += [
- '-O2',
- '-g',
-]
-
-# need static lib
-FORCE_STATIC_LIB = True
-
-# This code is only compiled for build-time tools,
-# so enabling RTTI should be fine.
-HOST_CXXFLAGS += [
- '-frtti',
- '-funsigned-char',
-]
-
-if CONFIG['OS_ARCH'] == 'Darwin':
- HOST_CXXFLAGS += [
- '-stdlib=libc++',
- ]
-
-include('/toolkit/crashreporter/crashreporter.mozbuild')
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h
deleted file mode 100644
index 59dda3160..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf/types.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 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.
-
-
-// This file contains some typedefs for basic types
-
-
-#ifndef _COMMON_DWARF_TYPES_H__
-#define _COMMON_DWARF_TYPES_H__
-
-#include <stdint.h>
-
-typedef signed char int8;
-typedef short int16;
-typedef int int32;
-typedef long long int64;
-
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef unsigned int uint32;
-typedef unsigned long long uint64;
-
-typedef intptr_t intptr;
-typedef uintptr_t uintptr;
-
-#endif // _COMMON_DWARF_TYPES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc
deleted file mode 100644
index 1bf1d96d5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.cc
+++ /dev/null
@@ -1,295 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// Implementation of google_breakpad::DwarfCFIToModule.
-// See dwarf_cfi_to_module.h for details.
-
-#include <sstream>
-
-#include "common/dwarf_cfi_to_module.h"
-
-namespace google_breakpad {
-
-using std::ostringstream;
-
-vector<string> DwarfCFIToModule::RegisterNames::MakeVector(
- const char * const *strings,
- size_t size) {
- vector<string> names(strings, strings + size);
- return names;
-}
-
-vector<string> DwarfCFIToModule::RegisterNames::I386() {
- static const char *const names[] = {
- "$eax", "$ecx", "$edx", "$ebx", "$esp", "$ebp", "$esi", "$edi",
- "$eip", "$eflags", "$unused1",
- "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
- "$unused2", "$unused3",
- "$xmm0", "$xmm1", "$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
- "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
- "$fcw", "$fsw", "$mxcsr",
- "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused4", "$unused5",
- "$tr", "$ldtr"
- };
-
- return MakeVector(names, sizeof(names) / sizeof(names[0]));
-}
-
-vector<string> DwarfCFIToModule::RegisterNames::X86_64() {
- static const char *const names[] = {
- "$rax", "$rdx", "$rcx", "$rbx", "$rsi", "$rdi", "$rbp", "$rsp",
- "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15",
- "$rip",
- "$xmm0","$xmm1","$xmm2", "$xmm3", "$xmm4", "$xmm5", "$xmm6", "$xmm7",
- "$xmm8","$xmm9","$xmm10","$xmm11","$xmm12","$xmm13","$xmm14","$xmm15",
- "$st0", "$st1", "$st2", "$st3", "$st4", "$st5", "$st6", "$st7",
- "$mm0", "$mm1", "$mm2", "$mm3", "$mm4", "$mm5", "$mm6", "$mm7",
- "$rflags",
- "$es", "$cs", "$ss", "$ds", "$fs", "$gs", "$unused1", "$unused2",
- "$fs.base", "$gs.base", "$unused3", "$unused4",
- "$tr", "$ldtr",
- "$mxcsr", "$fcw", "$fsw"
- };
-
- return MakeVector(names, sizeof(names) / sizeof(names[0]));
-}
-
-// Per ARM IHI 0040A, section 3.1
-vector<string> DwarfCFIToModule::RegisterNames::ARM() {
- static const char *const names[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "fps", "cpsr", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
- "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
- "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
- "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"
- };
-
- return MakeVector(names, sizeof(names) / sizeof(names[0]));
-}
-
-// Per ARM IHI 0057A, section 3.1
-vector<string> DwarfCFIToModule::RegisterNames::ARM64() {
- static const char *const names[] = {
- "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
- "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
- "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
- "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
- "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
- "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
- "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
- };
-
- return MakeVector(names, sizeof(names) / sizeof(names[0]));
-}
-
-vector<string> DwarfCFIToModule::RegisterNames::MIPS() {
- static const char* const kRegisterNames[] = {
- "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
- "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
- "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
- "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
- "$lo", "$hi", "$pc", "$f0", "$f2", "$f3", "$f4", "$f5",
- "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13",
- "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20",
- "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
- "$f28", "$f29", "$f30", "$f31", "$fcsr", "$fir"
- };
-
- return MakeVector(kRegisterNames,
- sizeof(kRegisterNames) / sizeof(kRegisterNames[0]));
-}
-
-bool DwarfCFIToModule::Entry(size_t offset, uint64 address, uint64 length,
- uint8 version, const string &augmentation,
- unsigned return_address) {
- assert(!entry_);
-
- // If dwarf2reader::CallFrameInfo can handle this version and
- // augmentation, then we should be okay with that, so there's no
- // need to check them here.
-
- // Get ready to collect entries.
- entry_ = new Module::StackFrameEntry;
- entry_->address = address;
- entry_->size = length;
- entry_offset_ = offset;
- return_address_ = return_address;
-
- // Breakpad STACK CFI records must provide a .ra rule, but DWARF CFI
- // may not establish any rule for .ra if the return address column
- // is an ordinary register, and that register holds the return
- // address on entry to the function. So establish an initial .ra
- // rule citing the return address register.
- if (return_address_ < register_names_.size())
- entry_->initial_rules[ra_name_] = register_names_[return_address_];
-
- return true;
-}
-
-string DwarfCFIToModule::RegisterName(int i) {
- assert(entry_);
- if (i < 0) {
- assert(i == kCFARegister);
- return cfa_name_;
- }
- unsigned reg = i;
- if (reg == return_address_)
- return ra_name_;
-
- // Ensure that a non-empty name exists for this register value.
- if (reg < register_names_.size() && !register_names_[reg].empty())
- return register_names_[reg];
-
- reporter_->UnnamedRegister(entry_offset_, reg);
- char buf[30];
- sprintf(buf, "unnamed_register%u", reg);
- return buf;
-}
-
-void DwarfCFIToModule::Record(Module::Address address, int reg,
- const string &rule) {
- assert(entry_);
-
- // Place the name in our global set of strings, and then use the string
- // from the set. Even though the assignment looks like a copy, all the
- // major std::string implementations use reference counting internally,
- // so the effect is to have all our data structures share copies of rules
- // whenever possible. Since register names are drawn from a
- // vector<string>, register names are already shared.
- string shared_rule = *common_strings_.insert(rule).first;
-
- // Is this one of this entry's initial rules?
- if (address == entry_->address)
- entry_->initial_rules[RegisterName(reg)] = shared_rule;
- // File it under the appropriate address.
- else
- entry_->rule_changes[address][RegisterName(reg)] = shared_rule;
-}
-
-bool DwarfCFIToModule::UndefinedRule(uint64 address, int reg) {
- reporter_->UndefinedNotSupported(entry_offset_, RegisterName(reg));
- // Treat this as a non-fatal error.
- return true;
-}
-
-bool DwarfCFIToModule::SameValueRule(uint64 address, int reg) {
- ostringstream s;
- s << RegisterName(reg);
- Record(address, reg, s.str());
- return true;
-}
-
-bool DwarfCFIToModule::OffsetRule(uint64 address, int reg,
- int base_register, long offset) {
- ostringstream s;
- s << RegisterName(base_register) << " " << offset << " + ^";
- Record(address, reg, s.str());
- return true;
-}
-
-bool DwarfCFIToModule::ValOffsetRule(uint64 address, int reg,
- int base_register, long offset) {
- ostringstream s;
- s << RegisterName(base_register) << " " << offset << " +";
- Record(address, reg, s.str());
- return true;
-}
-
-bool DwarfCFIToModule::RegisterRule(uint64 address, int reg,
- int base_register) {
- ostringstream s;
- s << RegisterName(base_register);
- Record(address, reg, s.str());
- return true;
-}
-
-bool DwarfCFIToModule::ExpressionRule(uint64 address, int reg,
- const string &expression) {
- reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
- // Treat this as a non-fatal error.
- return true;
-}
-
-bool DwarfCFIToModule::ValExpressionRule(uint64 address, int reg,
- const string &expression) {
- reporter_->ExpressionsNotSupported(entry_offset_, RegisterName(reg));
- // Treat this as a non-fatal error.
- return true;
-}
-
-bool DwarfCFIToModule::End() {
- module_->AddStackFrameEntry(entry_);
- entry_ = NULL;
- return true;
-}
-
-void DwarfCFIToModule::Reporter::UnnamedRegister(size_t offset, int reg) {
- fprintf(stderr, "%s, section '%s': "
- "the call frame entry at offset 0x%zx refers to register %d,"
- " whose name we don't know\n",
- file_.c_str(), section_.c_str(), offset, reg);
-}
-
-void DwarfCFIToModule::Reporter::UndefinedNotSupported(size_t offset,
- const string &reg) {
- fprintf(stderr, "%s, section '%s': "
- "the call frame entry at offset 0x%zx sets the rule for "
- "register '%s' to 'undefined', but the Breakpad symbol file format"
- " cannot express this\n",
- file_.c_str(), section_.c_str(), offset, reg.c_str());
-}
-
-void DwarfCFIToModule::Reporter::ExpressionsNotSupported(size_t offset,
- const string &reg) {
- fprintf(stderr, "%s, section '%s': "
- "the call frame entry at offset 0x%zx uses a DWARF expression to"
- " describe how to recover register '%s', "
- " but this translator cannot yet translate DWARF expressions to"
- " Breakpad postfix expressions\n",
- file_.c_str(), section_.c_str(), offset, reg.c_str());
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h
deleted file mode 100644
index 084b8f5a7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module.h
+++ /dev/null
@@ -1,202 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf_cfi_to_module.h: Define the DwarfCFIToModule class, which
-// accepts parsed DWARF call frame info and adds it to a
-// google_breakpad::Module object, which can write that information to
-// a Breakpad symbol file.
-
-#ifndef COMMON_LINUX_DWARF_CFI_TO_MODULE_H
-#define COMMON_LINUX_DWARF_CFI_TO_MODULE_H
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "common/module.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using dwarf2reader::CallFrameInfo;
-using google_breakpad::Module;
-using std::set;
-using std::vector;
-
-// A class that accepts parsed call frame information from the DWARF
-// CFI parser and populates a google_breakpad::Module object with the
-// contents.
-class DwarfCFIToModule: public CallFrameInfo::Handler {
- public:
-
- // DwarfCFIToModule uses an instance of this class to report errors
- // detected while converting DWARF CFI to Breakpad STACK CFI records.
- class Reporter {
- public:
- // Create a reporter that writes messages to the standard error
- // stream. FILE is the name of the file we're processing, and
- // SECTION is the name of the section within that file that we're
- // looking at (.debug_frame, .eh_frame, etc.).
- Reporter(const string &file, const string &section)
- : file_(file), section_(section) { }
- virtual ~Reporter() { }
-
- // The DWARF CFI entry at OFFSET cites register REG, but REG is not
- // covered by the vector of register names passed to the
- // DwarfCFIToModule constructor, nor does it match the return
- // address column number for this entry.
- virtual void UnnamedRegister(size_t offset, int reg);
-
- // The DWARF CFI entry at OFFSET says that REG is undefined, but the
- // Breakpad symbol file format cannot express this.
- virtual void UndefinedNotSupported(size_t offset, const string &reg);
-
- // The DWARF CFI entry at OFFSET says that REG uses a DWARF
- // expression to find its value, but DwarfCFIToModule is not
- // capable of translating DWARF expressions to Breakpad postfix
- // expressions.
- virtual void ExpressionsNotSupported(size_t offset, const string &reg);
-
- protected:
- string file_, section_;
- };
-
- // Register name tables. If TABLE is a vector returned by one of these
- // functions, then TABLE[R] is the name of the register numbered R in
- // DWARF call frame information.
- class RegisterNames {
- public:
- // Intel's "x86" or IA-32.
- static vector<string> I386();
-
- // AMD x86_64, AMD64, Intel EM64T, or Intel 64
- static vector<string> X86_64();
-
- // ARM.
- static vector<string> ARM();
-
- // ARM64, aka AARCH64.
- static vector<string> ARM64();
-
- // MIPS.
- static vector<string> MIPS();
-
- private:
- // Given STRINGS, an array of C strings with SIZE elements, return an
- // equivalent vector<string>.
- static vector<string> MakeVector(const char * const *strings, size_t size);
- };
-
- // Create a handler for the dwarf2reader::CallFrameInfo parser that
- // records the stack unwinding information it receives in MODULE.
- //
- // Use REGISTER_NAMES[I] as the name of register number I; *this
- // keeps a reference to the vector, so the vector should remain
- // alive for as long as the DwarfCFIToModule does.
- //
- // Use REPORTER for reporting problems encountered in the conversion
- // process.
- DwarfCFIToModule(Module *module, const vector<string> &register_names,
- Reporter *reporter)
- : module_(module), register_names_(register_names), reporter_(reporter),
- entry_(NULL), return_address_(-1), cfa_name_(".cfa"), ra_name_(".ra") {
- }
- virtual ~DwarfCFIToModule() { delete entry_; }
-
- virtual bool Entry(size_t offset, uint64 address, uint64 length,
- uint8 version, const string &augmentation,
- unsigned return_address);
- virtual bool UndefinedRule(uint64 address, int reg);
- virtual bool SameValueRule(uint64 address, int reg);
- virtual bool OffsetRule(uint64 address, int reg,
- int base_register, long offset);
- virtual bool ValOffsetRule(uint64 address, int reg,
- int base_register, long offset);
- virtual bool RegisterRule(uint64 address, int reg, int base_register);
- virtual bool ExpressionRule(uint64 address, int reg,
- const string &expression);
- virtual bool ValExpressionRule(uint64 address, int reg,
- const string &expression);
- virtual bool End();
-
- private:
- // Return the name to use for register REG.
- string RegisterName(int i);
-
- // Record RULE for register REG at ADDRESS.
- void Record(Module::Address address, int reg, const string &rule);
-
- // The module to which we should add entries.
- Module *module_;
-
- // Map from register numbers to register names.
- const vector<string> &register_names_;
-
- // The reporter to use to report problems.
- Reporter *reporter_;
-
- // The current entry we're constructing.
- Module::StackFrameEntry *entry_;
-
- // The section offset of the current frame description entry, for
- // use in error messages.
- size_t entry_offset_;
-
- // The return address column for that entry.
- unsigned return_address_;
-
- // The names of the return address and canonical frame address. Putting
- // these here instead of using string literals allows us to share their
- // texts in reference-counted std::string implementations (all the
- // popular ones). Many, many rules cite these strings.
- string cfa_name_, ra_name_;
-
- // A set of strings used by this CFI. Before storing a string in one of
- // our data structures, insert it into this set, and then use the string
- // from the set.
- //
- // Because std::string uses reference counting internally, simply using
- // strings from this set, even if passed by value, assigned, or held
- // directly in structures and containers (map<string, ...>, for example),
- // causes those strings to share a single instance of each distinct piece
- // of text.
- set<string> common_strings_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_DWARF_CFI_TO_MODULE_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module_unittest.cc
deleted file mode 100644
index 807d1b20c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cfi_to_module_unittest.cc
+++ /dev/null
@@ -1,306 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf_cfi_to_module_unittest.cc: Tests for google_breakpad::DwarfCFIToModule.
-
-#include <string>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf_cfi_to_module.h"
-#include "common/using_std_string.h"
-
-using std::vector;
-
-using google_breakpad::Module;
-using google_breakpad::DwarfCFIToModule;
-using testing::ContainerEq;
-using testing::Test;
-using testing::_;
-
-struct MockCFIReporter: public DwarfCFIToModule::Reporter {
- MockCFIReporter(const string &file, const string &section)
- : Reporter(file, section) { }
- MOCK_METHOD2(UnnamedRegister, void(size_t offset, int reg));
- MOCK_METHOD2(UndefinedNotSupported, void(size_t offset, const string &reg));
- MOCK_METHOD2(ExpressionsNotSupported, void(size_t offset, const string &reg));
-};
-
-struct DwarfCFIToModuleFixture {
- DwarfCFIToModuleFixture()
- : module("module name", "module os", "module arch", "module id"),
- reporter("reporter file", "reporter section"),
- handler(&module, register_names, &reporter) {
- register_names.push_back("reg0");
- register_names.push_back("reg1");
- register_names.push_back("reg2");
- register_names.push_back("reg3");
- register_names.push_back("reg4");
- register_names.push_back("reg5");
- register_names.push_back("reg6");
- register_names.push_back("reg7");
- register_names.push_back("sp");
- register_names.push_back("pc");
- register_names.push_back("");
-
- EXPECT_CALL(reporter, UnnamedRegister(_, _)).Times(0);
- EXPECT_CALL(reporter, UndefinedNotSupported(_, _)).Times(0);
- EXPECT_CALL(reporter, ExpressionsNotSupported(_, _)).Times(0);
- }
-
- Module module;
- vector<string> register_names;
- MockCFIReporter reporter;
- DwarfCFIToModule handler;
- vector<Module::StackFrameEntry *> entries;
-};
-
-class Entry: public DwarfCFIToModuleFixture, public Test { };
-
-TEST_F(Entry, Accept) {
- ASSERT_TRUE(handler.Entry(0x3b8961b8, 0xa21069698096fc98ULL,
- 0xb440ce248169c8d6ULL, 3, "", 0xea93c106));
- ASSERT_TRUE(handler.End());
- module.GetStackFrameEntries(&entries);
- EXPECT_EQ(1U, entries.size());
- EXPECT_EQ(0xa21069698096fc98ULL, entries[0]->address);
- EXPECT_EQ(0xb440ce248169c8d6ULL, entries[0]->size);
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Entry, AcceptOldVersion) {
- ASSERT_TRUE(handler.Entry(0xeb60e0fc, 0x75b8806bb09eab78ULL,
- 0xc771f44958d40bbcULL, 1, "", 0x093c945e));
- ASSERT_TRUE(handler.End());
- module.GetStackFrameEntries(&entries);
- EXPECT_EQ(1U, entries.size());
- EXPECT_EQ(0x75b8806bb09eab78ULL, entries[0]->address);
- EXPECT_EQ(0xc771f44958d40bbcULL, entries[0]->size);
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-struct RuleFixture: public DwarfCFIToModuleFixture {
- RuleFixture() : DwarfCFIToModuleFixture() {
- entry_address = 0x89327ebf86b47492ULL;
- entry_size = 0x2f8cd573072fe02aULL;
- return_reg = 0x7886a346;
- }
- void StartEntry() {
- ASSERT_TRUE(handler.Entry(0x4445c05c, entry_address, entry_size,
- 3, "", return_reg));
- }
- void CheckEntry() {
- module.GetStackFrameEntries(&entries);
- EXPECT_EQ(1U, entries.size());
- EXPECT_EQ(entry_address, entries[0]->address);
- EXPECT_EQ(entry_size, entries[0]->size);
- }
- uint64 entry_address, entry_size;
- unsigned return_reg;
-};
-
-class Rule: public RuleFixture, public Test { };
-
-TEST_F(Rule, UndefinedRule) {
- EXPECT_CALL(reporter, UndefinedNotSupported(_, "reg7"));
- StartEntry();
- ASSERT_TRUE(handler.UndefinedRule(entry_address, 7));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, RegisterWithEmptyName) {
- EXPECT_CALL(reporter, UnnamedRegister(_, 10));
- EXPECT_CALL(reporter, UndefinedNotSupported(_, "unnamed_register10"));
- StartEntry();
- ASSERT_TRUE(handler.UndefinedRule(entry_address, 10));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, SameValueRule) {
- StartEntry();
- ASSERT_TRUE(handler.SameValueRule(entry_address, 6));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- Module::RuleMap expected_initial;
- expected_initial["reg6"] = "reg6";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, OffsetRule) {
- StartEntry();
- ASSERT_TRUE(handler.OffsetRule(entry_address + 1, return_reg,
- DwarfCFIToModule::kCFARegister,
- 16927065));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- Module::RuleChangeMap expected_changes;
- expected_changes[entry_address + 1][".ra"] = ".cfa 16927065 + ^";
- EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
-}
-
-TEST_F(Rule, OffsetRuleNegative) {
- StartEntry();
- ASSERT_TRUE(handler.OffsetRule(entry_address + 1,
- DwarfCFIToModule::kCFARegister, 4, -34530721));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- Module::RuleChangeMap expected_changes;
- expected_changes[entry_address + 1][".cfa"] = "reg4 -34530721 + ^";
- EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
-}
-
-TEST_F(Rule, ValOffsetRule) {
- // Use an unnamed register number, to exercise that branch of RegisterName.
- EXPECT_CALL(reporter, UnnamedRegister(_, 11));
- StartEntry();
- ASSERT_TRUE(handler.ValOffsetRule(entry_address + 0x5ab7,
- DwarfCFIToModule::kCFARegister,
- 11, 61812979));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- Module::RuleChangeMap expected_changes;
- expected_changes[entry_address + 0x5ab7][".cfa"] =
- "unnamed_register11 61812979 +";
- EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
-}
-
-TEST_F(Rule, RegisterRule) {
- StartEntry();
- ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 3));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- Module::RuleMap expected_initial;
- expected_initial[".ra"] = "reg3";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, ExpressionRule) {
- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg2"));
- StartEntry();
- ASSERT_TRUE(handler.ExpressionRule(entry_address + 0xf326, 2,
- "it takes two to tango"));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, ValExpressionRule) {
- EXPECT_CALL(reporter, ExpressionsNotSupported(_, "reg0"));
- StartEntry();
- ASSERT_TRUE(handler.ValExpressionRule(entry_address + 0x6367, 0,
- "bit off more than he could chew"));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- EXPECT_EQ(0U, entries[0]->initial_rules.size());
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, DefaultReturnAddressRule) {
- return_reg = 2;
- StartEntry();
- ASSERT_TRUE(handler.RegisterRule(entry_address, 0, 1));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- Module::RuleMap expected_initial;
- expected_initial[".ra"] = "reg2";
- expected_initial["reg0"] = "reg1";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, DefaultReturnAddressRuleOverride) {
- return_reg = 2;
- StartEntry();
- ASSERT_TRUE(handler.RegisterRule(entry_address, return_reg, 1));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- Module::RuleMap expected_initial;
- expected_initial[".ra"] = "reg1";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
- EXPECT_EQ(0U, entries[0]->rule_changes.size());
-}
-
-TEST_F(Rule, DefaultReturnAddressRuleLater) {
- return_reg = 2;
- StartEntry();
- ASSERT_TRUE(handler.RegisterRule(entry_address + 1, return_reg, 1));
- ASSERT_TRUE(handler.End());
- CheckEntry();
- Module::RuleMap expected_initial;
- expected_initial[".ra"] = "reg2";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(expected_initial));
- Module::RuleChangeMap expected_changes;
- expected_changes[entry_address + 1][".ra"] = "reg1";
- EXPECT_THAT(entries[0]->rule_changes, ContainerEq(expected_changes));
-}
-
-TEST(RegisterNames, I386) {
- vector<string> names = DwarfCFIToModule::RegisterNames::I386();
-
- EXPECT_EQ("$eax", names[0]);
- EXPECT_EQ("$ecx", names[1]);
- EXPECT_EQ("$esp", names[4]);
- EXPECT_EQ("$eip", names[8]);
-}
-
-TEST(RegisterNames, ARM) {
- vector<string> names = DwarfCFIToModule::RegisterNames::ARM();
-
- EXPECT_EQ("r0", names[0]);
- EXPECT_EQ("r10", names[10]);
- EXPECT_EQ("sp", names[13]);
- EXPECT_EQ("lr", names[14]);
- EXPECT_EQ("pc", names[15]);
-}
-
-TEST(RegisterNames, X86_64) {
- vector<string> names = DwarfCFIToModule::RegisterNames::X86_64();
-
- EXPECT_EQ("$rax", names[0]);
- EXPECT_EQ("$rdx", names[1]);
- EXPECT_EQ("$rbp", names[6]);
- EXPECT_EQ("$rsp", names[7]);
- EXPECT_EQ("$rip", names[16]);
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc
deleted file mode 100644
index 479e39b22..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.cc
+++ /dev/null
@@ -1,1075 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// Implement the DwarfCUToModule class; see dwarf_cu_to_module.h.
-
-// For <inttypes.h> PRI* macros, before anything else might #include it.
-#ifndef __STDC_FORMAT_MACROS
-#define __STDC_FORMAT_MACROS
-#endif /* __STDC_FORMAT_MACROS */
-
-#include "common/dwarf_cu_to_module.h"
-
-#include <assert.h>
-#if !defined(__ANDROID__)
-#include <cxxabi.h>
-#endif
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "common/dwarf_line_to_module.h"
-#include "common/unordered.h"
-
-namespace google_breakpad {
-
-using std::map;
-using std::pair;
-using std::sort;
-using std::vector;
-
-// Data provided by a DWARF specification DIE.
-//
-// In DWARF, the DIE for a definition may contain a DW_AT_specification
-// attribute giving the offset of the corresponding declaration DIE, and
-// the definition DIE may omit information given in the declaration. For
-// example, it's common for a function's address range to appear only in
-// its definition DIE, but its name to appear only in its declaration
-// DIE.
-//
-// The dumper needs to be able to follow DW_AT_specification links to
-// bring all this information together in a FUNC record. Conveniently,
-// DIEs that are the target of such links have a DW_AT_declaration flag
-// set, so we can identify them when we first see them, and record their
-// contents for later reference.
-//
-// A Specification holds information gathered from a declaration DIE that
-// we may need if we find a DW_AT_specification link pointing to it.
-struct DwarfCUToModule::Specification {
- // The qualified name that can be found by demangling DW_AT_MIPS_linkage_name.
- string qualified_name;
-
- // The name of the enclosing scope, or the empty string if there is none.
- string enclosing_name;
-
- // The name for the specification DIE itself, without any enclosing
- // name components.
- string unqualified_name;
-};
-
-// An abstract origin -- base definition of an inline function.
-struct AbstractOrigin {
- AbstractOrigin() : name() {}
- explicit AbstractOrigin(const string& name) : name(name) {}
-
- string name;
-};
-
-typedef map<uint64, AbstractOrigin> AbstractOriginByOffset;
-
-// Data global to the DWARF-bearing file that is private to the
-// DWARF-to-Module process.
-struct DwarfCUToModule::FilePrivate {
- // A set of strings used in this CU. Before storing a string in one of
- // our data structures, insert it into this set, and then use the string
- // from the set.
- //
- // In some STL implementations, strings are reference-counted internally,
- // meaning that simply using strings from this set, even if passed by
- // value, assigned, or held directly in structures and containers
- // (map<string, ...>, for example), causes those strings to share a
- // single instance of each distinct piece of text. GNU's libstdc++ uses
- // reference counts, and I believe MSVC did as well, at some point.
- // However, C++ '11 implementations are moving away from reference
- // counting.
- //
- // In other implementations, string assignments copy the string's text,
- // so this set will actually hold yet another copy of the string (although
- // everything will still work). To improve memory consumption portably,
- // we will probably need to use pointers to strings held in this set.
- unordered_set<string> common_strings;
-
- // A map from offsets of DIEs within the .debug_info section to
- // Specifications describing those DIEs. Specification references can
- // cross compilation unit boundaries.
- SpecificationByOffset specifications;
-
- AbstractOriginByOffset origins;
-};
-
-DwarfCUToModule::FileContext::FileContext(const string &filename,
- Module *module,
- bool handle_inter_cu_refs)
- : filename_(filename),
- module_(module),
- handle_inter_cu_refs_(handle_inter_cu_refs),
- file_private_(new FilePrivate()) {
-}
-
-DwarfCUToModule::FileContext::~FileContext() {
-}
-
-void DwarfCUToModule::FileContext::AddSectionToSectionMap(
- const string& name, const uint8_t *contents, uint64 length) {
- section_map_[name] = std::make_pair(contents, length);
-}
-
-void DwarfCUToModule::FileContext::ClearSectionMapForTest() {
- section_map_.clear();
-}
-
-const dwarf2reader::SectionMap&
-DwarfCUToModule::FileContext::section_map() const {
- return section_map_;
-}
-
-void DwarfCUToModule::FileContext::ClearSpecifications() {
- if (!handle_inter_cu_refs_)
- file_private_->specifications.clear();
-}
-
-bool DwarfCUToModule::FileContext::IsUnhandledInterCUReference(
- uint64 offset, uint64 compilation_unit_start) const {
- if (handle_inter_cu_refs_)
- return false;
- return offset < compilation_unit_start;
-}
-
-// Information global to the particular compilation unit we're
-// parsing. This is for data shared across the CU's entire DIE tree,
-// and parameters from the code invoking the CU parser.
-struct DwarfCUToModule::CUContext {
- CUContext(FileContext *file_context_arg, WarningReporter *reporter_arg)
- : file_context(file_context_arg),
- reporter(reporter_arg),
- language(Language::CPlusPlus) {}
-
- ~CUContext() {
- for (vector<Module::Function *>::iterator it = functions.begin();
- it != functions.end(); ++it) {
- delete *it;
- }
- };
-
- // The DWARF-bearing file into which this CU was incorporated.
- FileContext *file_context;
-
- // For printing error messages.
- WarningReporter *reporter;
-
- // The source language of this compilation unit.
- const Language *language;
-
- // The functions defined in this compilation unit. We accumulate
- // them here during parsing. Then, in DwarfCUToModule::Finish, we
- // assign them lines and add them to file_context->module.
- //
- // Destroying this destroys all the functions this vector points to.
- vector<Module::Function *> functions;
-};
-
-// Information about the context of a particular DIE. This is for
-// information that changes as we descend the tree towards the leaves:
-// the containing classes/namespaces, etc.
-struct DwarfCUToModule::DIEContext {
- // The fully-qualified name of the context. For example, for a
- // tree like:
- //
- // DW_TAG_namespace Foo
- // DW_TAG_class Bar
- // DW_TAG_subprogram Baz
- //
- // in a C++ compilation unit, the DIEContext's name for the
- // DW_TAG_subprogram DIE would be "Foo::Bar". The DIEContext's
- // name for the DW_TAG_namespace DIE would be "".
- string name;
-};
-
-// An abstract base class for all the dumper's DIE handlers.
-class DwarfCUToModule::GenericDIEHandler: public dwarf2reader::DIEHandler {
- public:
- // Create a handler for the DIE at OFFSET whose compilation unit is
- // described by CU_CONTEXT, and whose immediate context is described
- // by PARENT_CONTEXT.
- GenericDIEHandler(CUContext *cu_context, DIEContext *parent_context,
- uint64 offset)
- : cu_context_(cu_context),
- parent_context_(parent_context),
- offset_(offset),
- declaration_(false),
- specification_(NULL) { }
-
- // Derived classes' ProcessAttributeUnsigned can defer to this to
- // handle DW_AT_declaration, or simply not override it.
- void ProcessAttributeUnsigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
-
- // Derived classes' ProcessAttributeReference can defer to this to
- // handle DW_AT_specification, or simply not override it.
- void ProcessAttributeReference(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
-
- // Derived classes' ProcessAttributeReference can defer to this to
- // handle DW_AT_specification, or simply not override it.
- void ProcessAttributeString(enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data);
-
- protected:
- // Compute and return the fully-qualified name of the DIE. If this
- // DIE is a declaration DIE, to be cited by other DIEs'
- // DW_AT_specification attributes, record its enclosing name and
- // unqualified name in the specification table.
- //
- // Use this from EndAttributes member functions, not ProcessAttribute*
- // functions; only the former can be sure that all the DIE's attributes
- // have been seen.
- string ComputeQualifiedName();
-
- CUContext *cu_context_;
- DIEContext *parent_context_;
- uint64 offset_;
-
- // Place the name in the global set of strings. Even though this looks
- // like a copy, all the major std::string implementations use reference
- // counting internally, so the effect is to have all the data structures
- // share copies of strings whenever possible.
- // FIXME: Should this return something like a string_ref to avoid the
- // assumption about how strings are implemented?
- string AddStringToPool(const string &str);
-
- // If this DIE has a DW_AT_declaration attribute, this is its value.
- // It is false on DIEs with no DW_AT_declaration attribute.
- bool declaration_;
-
- // If this DIE has a DW_AT_specification attribute, this is the
- // Specification structure for the DIE the attribute refers to.
- // Otherwise, this is NULL.
- Specification *specification_;
-
- // The value of the DW_AT_name attribute, or the empty string if the
- // DIE has no such attribute.
- string name_attribute_;
-
- // The demangled value of the DW_AT_MIPS_linkage_name attribute, or the empty
- // string if the DIE has no such attribute or its content could not be
- // demangled.
- string demangled_name_;
-};
-
-void DwarfCUToModule::GenericDIEHandler::ProcessAttributeUnsigned(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- switch (attr) {
- case dwarf2reader::DW_AT_declaration: declaration_ = (data != 0); break;
- default: break;
- }
-}
-
-void DwarfCUToModule::GenericDIEHandler::ProcessAttributeReference(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- switch (attr) {
- case dwarf2reader::DW_AT_specification: {
- FileContext *file_context = cu_context_->file_context;
- if (file_context->IsUnhandledInterCUReference(
- data, cu_context_->reporter->cu_offset())) {
- cu_context_->reporter->UnhandledInterCUReference(offset_, data);
- break;
- }
- // Find the Specification to which this attribute refers, and
- // set specification_ appropriately. We could do more processing
- // here, but it's better to leave the real work to our
- // EndAttribute member function, at which point we know we have
- // seen all the DIE's attributes.
- SpecificationByOffset *specifications =
- &file_context->file_private_->specifications;
- SpecificationByOffset::iterator spec = specifications->find(data);
- if (spec != specifications->end()) {
- specification_ = &spec->second;
- } else {
- // Technically, there's no reason a DW_AT_specification
- // couldn't be a forward reference, but supporting that would
- // be a lot of work (changing to a two-pass structure), and I
- // don't think any producers we care about ever emit such
- // things.
- cu_context_->reporter->UnknownSpecification(offset_, data);
- }
- break;
- }
- default: break;
- }
-}
-
-string DwarfCUToModule::GenericDIEHandler::AddStringToPool(const string &str) {
- pair<unordered_set<string>::iterator, bool> result =
- cu_context_->file_context->file_private_->common_strings.insert(str);
- return *result.first;
-}
-
-void DwarfCUToModule::GenericDIEHandler::ProcessAttributeString(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data) {
- switch (attr) {
- case dwarf2reader::DW_AT_name:
- name_attribute_ = AddStringToPool(data);
- break;
- case dwarf2reader::DW_AT_MIPS_linkage_name: {
- char* demangled = NULL;
- int status = -1;
-#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle.
- demangled = abi::__cxa_demangle(data.c_str(), NULL, NULL, &status);
-#endif
- if (status != 0) {
- cu_context_->reporter->DemangleError(data, status);
- demangled_name_ = "";
- break;
- }
- if (demangled) {
- demangled_name_ = AddStringToPool(demangled);
- free(reinterpret_cast<void*>(demangled));
- }
- break;
- }
- default: break;
- }
-}
-
-string DwarfCUToModule::GenericDIEHandler::ComputeQualifiedName() {
- // Use the demangled name, if one is available. Demangled names are
- // preferable to those inferred from the DWARF structure because they
- // include argument types.
- const string *qualified_name = NULL;
- if (!demangled_name_.empty()) {
- // Found it is this DIE.
- qualified_name = &demangled_name_;
- } else if (specification_ && !specification_->qualified_name.empty()) {
- // Found it on the specification.
- qualified_name = &specification_->qualified_name;
- }
-
- const string *unqualified_name = NULL;
- const string *enclosing_name;
- if (!qualified_name) {
- // Find the unqualified name. If the DIE has its own DW_AT_name
- // attribute, then use that; otherwise, check the specification.
- if (!name_attribute_.empty())
- unqualified_name = &name_attribute_;
- else if (specification_)
- unqualified_name = &specification_->unqualified_name;
-
- // Find the name of the enclosing context. If this DIE has a
- // specification, it's the specification's enclosing context that
- // counts; otherwise, use this DIE's context.
- if (specification_)
- enclosing_name = &specification_->enclosing_name;
- else
- enclosing_name = &parent_context_->name;
- }
-
- // Prepare the return value before upcoming mutations possibly invalidate the
- // existing pointers.
- string return_value;
- if (qualified_name) {
- return_value = *qualified_name;
- } else if (unqualified_name && enclosing_name) {
- // Combine the enclosing name and unqualified name to produce our
- // own fully-qualified name.
- return_value = cu_context_->language->MakeQualifiedName(*enclosing_name,
- *unqualified_name);
- }
-
- // If this DIE was marked as a declaration, record its names in the
- // specification table.
- if ((declaration_ && qualified_name) ||
- (unqualified_name && enclosing_name)) {
- Specification spec;
- if (qualified_name) {
- spec.qualified_name = *qualified_name;
- } else {
- spec.enclosing_name = *enclosing_name;
- spec.unqualified_name = *unqualified_name;
- }
- cu_context_->file_context->file_private_->specifications[offset_] = spec;
- }
-
- return return_value;
-}
-
-// A handler class for DW_TAG_subprogram DIEs.
-class DwarfCUToModule::FuncHandler: public GenericDIEHandler {
- public:
- FuncHandler(CUContext *cu_context, DIEContext *parent_context,
- uint64 offset)
- : GenericDIEHandler(cu_context, parent_context, offset),
- low_pc_(0), high_pc_(0), high_pc_form_(dwarf2reader::DW_FORM_addr),
- abstract_origin_(NULL), inline_(false) { }
- void ProcessAttributeUnsigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
- void ProcessAttributeSigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data);
- void ProcessAttributeReference(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
-
- bool EndAttributes();
- void Finish();
-
- private:
- // The fully-qualified name, as derived from name_attribute_,
- // specification_, parent_context_. Computed in EndAttributes.
- string name_;
- uint64 low_pc_, high_pc_; // DW_AT_low_pc, DW_AT_high_pc
- DwarfForm high_pc_form_; // DW_AT_high_pc can be length or address.
- const AbstractOrigin* abstract_origin_;
- bool inline_;
-};
-
-void DwarfCUToModule::FuncHandler::ProcessAttributeUnsigned(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- switch (attr) {
- // If this attribute is present at all --- even if its value is
- // DW_INL_not_inlined --- then GCC may cite it as someone else's
- // DW_AT_abstract_origin attribute.
- case dwarf2reader::DW_AT_inline: inline_ = true; break;
-
- case dwarf2reader::DW_AT_low_pc: low_pc_ = data; break;
- case dwarf2reader::DW_AT_high_pc:
- high_pc_form_ = form;
- high_pc_ = data;
- break;
-
- default:
- GenericDIEHandler::ProcessAttributeUnsigned(attr, form, data);
- break;
- }
-}
-
-void DwarfCUToModule::FuncHandler::ProcessAttributeSigned(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) {
- switch (attr) {
- // If this attribute is present at all --- even if its value is
- // DW_INL_not_inlined --- then GCC may cite it as someone else's
- // DW_AT_abstract_origin attribute.
- case dwarf2reader::DW_AT_inline: inline_ = true; break;
-
- default:
- break;
- }
-}
-
-void DwarfCUToModule::FuncHandler::ProcessAttributeReference(
- enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- switch (attr) {
- case dwarf2reader::DW_AT_abstract_origin: {
- const AbstractOriginByOffset& origins =
- cu_context_->file_context->file_private_->origins;
- AbstractOriginByOffset::const_iterator origin = origins.find(data);
- if (origin != origins.end()) {
- abstract_origin_ = &(origin->second);
- } else {
- cu_context_->reporter->UnknownAbstractOrigin(offset_, data);
- }
- break;
- }
- default:
- GenericDIEHandler::ProcessAttributeReference(attr, form, data);
- break;
- }
-}
-
-bool DwarfCUToModule::FuncHandler::EndAttributes() {
- // Compute our name, and record a specification, if appropriate.
- name_ = ComputeQualifiedName();
- if (name_.empty() && abstract_origin_) {
- name_ = abstract_origin_->name;
- }
- return true;
-}
-
-void DwarfCUToModule::FuncHandler::Finish() {
- // Make high_pc_ an address, if it isn't already.
- if (high_pc_form_ != dwarf2reader::DW_FORM_addr) {
- high_pc_ += low_pc_;
- }
-
- // Did we collect the information we need? Not all DWARF function
- // entries have low and high addresses (for example, inlined
- // functions that were never used), but all the ones we're
- // interested in cover a non-empty range of bytes.
- if (low_pc_ < high_pc_) {
- // Malformed DWARF may omit the name, but all Module::Functions must
- // have names.
- string name;
- if (!name_.empty()) {
- name = name_;
- } else {
- cu_context_->reporter->UnnamedFunction(offset_);
- name = "<name omitted>";
- }
-
- // Create a Module::Function based on the data we've gathered, and
- // add it to the functions_ list.
- scoped_ptr<Module::Function> func(new Module::Function(name, low_pc_));
- func->size = high_pc_ - low_pc_;
- func->parameter_size = 0;
- if (func->address) {
- // If the function address is zero this is a sign that this function
- // description is just empty debug data and should just be discarded.
- cu_context_->functions.push_back(func.release());
- }
- } else if (inline_) {
- AbstractOrigin origin(name_);
- cu_context_->file_context->file_private_->origins[offset_] = origin;
- }
-}
-
-// A handler for DIEs that contain functions and contribute a
-// component to their names: namespaces, classes, etc.
-class DwarfCUToModule::NamedScopeHandler: public GenericDIEHandler {
- public:
- NamedScopeHandler(CUContext *cu_context, DIEContext *parent_context,
- uint64 offset)
- : GenericDIEHandler(cu_context, parent_context, offset) { }
- bool EndAttributes();
- DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag);
-
- private:
- DIEContext child_context_; // A context for our children.
-};
-
-bool DwarfCUToModule::NamedScopeHandler::EndAttributes() {
- child_context_.name = ComputeQualifiedName();
- return true;
-}
-
-dwarf2reader::DIEHandler *DwarfCUToModule::NamedScopeHandler::FindChildHandler(
- uint64 offset,
- enum DwarfTag tag) {
- switch (tag) {
- case dwarf2reader::DW_TAG_subprogram:
- return new FuncHandler(cu_context_, &child_context_, offset);
- case dwarf2reader::DW_TAG_namespace:
- case dwarf2reader::DW_TAG_class_type:
- case dwarf2reader::DW_TAG_structure_type:
- case dwarf2reader::DW_TAG_union_type:
- return new NamedScopeHandler(cu_context_, &child_context_, offset);
- default:
- return NULL;
- }
-}
-
-void DwarfCUToModule::WarningReporter::CUHeading() {
- if (printed_cu_header_)
- return;
- fprintf(stderr, "%s: in compilation unit '%s' (offset 0x%llx):\n",
- filename_.c_str(), cu_name_.c_str(), cu_offset_);
- printed_cu_header_ = true;
-}
-
-void DwarfCUToModule::WarningReporter::UnknownSpecification(uint64 offset,
- uint64 target) {
- CUHeading();
- fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_specification"
- " attribute referring to the die at offset 0x%llx, which either"
- " was not marked as a declaration, or comes later in the file\n",
- filename_.c_str(), offset, target);
-}
-
-void DwarfCUToModule::WarningReporter::UnknownAbstractOrigin(uint64 offset,
- uint64 target) {
- CUHeading();
- fprintf(stderr, "%s: the DIE at offset 0x%llx has a DW_AT_abstract_origin"
- " attribute referring to the die at offset 0x%llx, which either"
- " was not marked as an inline, or comes later in the file\n",
- filename_.c_str(), offset, target);
-}
-
-void DwarfCUToModule::WarningReporter::MissingSection(const string &name) {
- CUHeading();
- fprintf(stderr, "%s: warning: couldn't find DWARF '%s' section\n",
- filename_.c_str(), name.c_str());
-}
-
-void DwarfCUToModule::WarningReporter::BadLineInfoOffset(uint64 offset) {
- CUHeading();
- fprintf(stderr, "%s: warning: line number data offset beyond end"
- " of '.debug_line' section\n",
- filename_.c_str());
-}
-
-void DwarfCUToModule::WarningReporter::UncoveredHeading() {
- if (printed_unpaired_header_)
- return;
- CUHeading();
- fprintf(stderr, "%s: warning: skipping unpaired lines/functions:\n",
- filename_.c_str());
- printed_unpaired_header_ = true;
-}
-
-void DwarfCUToModule::WarningReporter::UncoveredFunction(
- const Module::Function &function) {
- if (!uncovered_warnings_enabled_)
- return;
- UncoveredHeading();
- fprintf(stderr, " function%s: %s\n",
- function.size == 0 ? " (zero-length)" : "",
- function.name.c_str());
-}
-
-void DwarfCUToModule::WarningReporter::UncoveredLine(const Module::Line &line) {
- if (!uncovered_warnings_enabled_)
- return;
- UncoveredHeading();
- fprintf(stderr, " line%s: %s:%d at 0x%" PRIx64 "\n",
- (line.size == 0 ? " (zero-length)" : ""),
- line.file->name.c_str(), line.number, line.address);
-}
-
-void DwarfCUToModule::WarningReporter::UnnamedFunction(uint64 offset) {
- CUHeading();
- fprintf(stderr, "%s: warning: function at offset 0x%llx has no name\n",
- filename_.c_str(), offset);
-}
-
-void DwarfCUToModule::WarningReporter::DemangleError(
- const string &input, int error) {
- CUHeading();
- fprintf(stderr, "%s: warning: failed to demangle %s with error %d\n",
- filename_.c_str(), input.c_str(), error);
-}
-
-void DwarfCUToModule::WarningReporter::UnhandledInterCUReference(
- uint64 offset, uint64 target) {
- CUHeading();
- fprintf(stderr, "%s: warning: the DIE at offset 0x%llx has a "
- "DW_FORM_ref_addr attribute with an inter-CU reference to "
- "0x%llx, but inter-CU reference handling is turned off.\n",
- filename_.c_str(), offset, target);
-}
-
-DwarfCUToModule::DwarfCUToModule(FileContext *file_context,
- LineToModuleHandler *line_reader,
- WarningReporter *reporter)
- : line_reader_(line_reader),
- cu_context_(new CUContext(file_context, reporter)),
- child_context_(new DIEContext()),
- has_source_line_info_(false) {
-}
-
-DwarfCUToModule::~DwarfCUToModule() {
-}
-
-void DwarfCUToModule::ProcessAttributeSigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data) {
- switch (attr) {
- case dwarf2reader::DW_AT_language: // source language of this CU
- SetLanguage(static_cast<DwarfLanguage>(data));
- break;
- default:
- break;
- }
-}
-
-void DwarfCUToModule::ProcessAttributeUnsigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data) {
- switch (attr) {
- case dwarf2reader::DW_AT_stmt_list: // Line number information.
- has_source_line_info_ = true;
- source_line_offset_ = data;
- break;
- case dwarf2reader::DW_AT_language: // source language of this CU
- SetLanguage(static_cast<DwarfLanguage>(data));
- break;
- default:
- break;
- }
-}
-
-void DwarfCUToModule::ProcessAttributeString(enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data) {
- switch (attr) {
- case dwarf2reader::DW_AT_name:
- cu_context_->reporter->SetCUName(data);
- break;
- case dwarf2reader::DW_AT_comp_dir:
- line_reader_->StartCompilationUnit(data);
- break;
- default:
- break;
- }
-}
-
-bool DwarfCUToModule::EndAttributes() {
- return true;
-}
-
-dwarf2reader::DIEHandler *DwarfCUToModule::FindChildHandler(
- uint64 offset,
- enum DwarfTag tag) {
- switch (tag) {
- case dwarf2reader::DW_TAG_subprogram:
- return new FuncHandler(cu_context_.get(), child_context_.get(), offset);
- case dwarf2reader::DW_TAG_namespace:
- case dwarf2reader::DW_TAG_class_type:
- case dwarf2reader::DW_TAG_structure_type:
- case dwarf2reader::DW_TAG_union_type:
- return new NamedScopeHandler(cu_context_.get(), child_context_.get(),
- offset);
- default:
- return NULL;
- }
-}
-
-void DwarfCUToModule::SetLanguage(DwarfLanguage language) {
- switch (language) {
- case dwarf2reader::DW_LANG_Java:
- cu_context_->language = Language::Java;
- break;
-
- // DWARF has no generic language code for assembly language; this is
- // what the GNU toolchain uses.
- case dwarf2reader::DW_LANG_Mips_Assembler:
- cu_context_->language = Language::Assembler;
- break;
-
- // C++ covers so many cases that it probably has some way to cope
- // with whatever the other languages throw at us. So make it the
- // default.
- //
- // Objective C and Objective C++ seem to create entries for
- // methods whose DW_AT_name values are already fully-qualified:
- // "-[Classname method:]". These appear at the top level.
- //
- // DWARF data for C should never include namespaces or functions
- // nested in struct types, but if it ever does, then C++'s
- // notation is probably not a bad choice for that.
- default:
- case dwarf2reader::DW_LANG_ObjC:
- case dwarf2reader::DW_LANG_ObjC_plus_plus:
- case dwarf2reader::DW_LANG_C:
- case dwarf2reader::DW_LANG_C89:
- case dwarf2reader::DW_LANG_C99:
- case dwarf2reader::DW_LANG_C_plus_plus:
- cu_context_->language = Language::CPlusPlus;
- break;
- }
-}
-
-void DwarfCUToModule::ReadSourceLines(uint64 offset) {
- const dwarf2reader::SectionMap &section_map
- = cu_context_->file_context->section_map();
- dwarf2reader::SectionMap::const_iterator map_entry
- = section_map.find(".debug_line");
- // Mac OS X puts DWARF data in sections whose names begin with "__"
- // instead of ".".
- if (map_entry == section_map.end())
- map_entry = section_map.find("__debug_line");
- if (map_entry == section_map.end()) {
- cu_context_->reporter->MissingSection(".debug_line");
- return;
- }
- const uint8_t *section_start = map_entry->second.first;
- uint64 section_length = map_entry->second.second;
- if (offset >= section_length) {
- cu_context_->reporter->BadLineInfoOffset(offset);
- return;
- }
- line_reader_->ReadProgram(section_start + offset, section_length - offset,
- cu_context_->file_context->module_, &lines_);
-}
-
-namespace {
-// Return true if ADDRESS falls within the range of ITEM.
-template <class T>
-inline bool within(const T &item, Module::Address address) {
- // Because Module::Address is unsigned, and unsigned arithmetic
- // wraps around, this will be false if ADDRESS falls before the
- // start of ITEM, or if it falls after ITEM's end.
- return address - item.address < item.size;
-}
-}
-
-void DwarfCUToModule::AssignLinesToFunctions() {
- vector<Module::Function *> *functions = &cu_context_->functions;
- WarningReporter *reporter = cu_context_->reporter;
-
- // This would be simpler if we assumed that source line entries
- // don't cross function boundaries. However, there's no real reason
- // to assume that (say) a series of function definitions on the same
- // line wouldn't get coalesced into one line number entry. The
- // DWARF spec certainly makes no such promises.
- //
- // So treat the functions and lines as peers, and take the trouble
- // to compute their ranges' intersections precisely. In any case,
- // the hair here is a constant factor for performance; the
- // complexity from here on out is linear.
-
- // Put both our functions and lines in order by address.
- std::sort(functions->begin(), functions->end(),
- Module::Function::CompareByAddress);
- std::sort(lines_.begin(), lines_.end(), Module::Line::CompareByAddress);
-
- // The last line that we used any piece of. We use this only for
- // generating warnings.
- const Module::Line *last_line_used = NULL;
-
- // The last function and line we warned about --- so we can avoid
- // doing so more than once.
- const Module::Function *last_function_cited = NULL;
- const Module::Line *last_line_cited = NULL;
-
- // Make a single pass through both vectors from lower to higher
- // addresses, populating each Function's lines vector with lines
- // from our lines_ vector that fall within the function's address
- // range.
- vector<Module::Function *>::iterator func_it = functions->begin();
- vector<Module::Line>::const_iterator line_it = lines_.begin();
-
- Module::Address current;
-
- // Pointers to the referents of func_it and line_it, or NULL if the
- // iterator is at the end of the sequence.
- Module::Function *func;
- const Module::Line *line;
-
- // Start current at the beginning of the first line or function,
- // whichever is earlier.
- if (func_it != functions->end() && line_it != lines_.end()) {
- func = *func_it;
- line = &*line_it;
- current = std::min(func->address, line->address);
- } else if (line_it != lines_.end()) {
- func = NULL;
- line = &*line_it;
- current = line->address;
- } else if (func_it != functions->end()) {
- func = *func_it;
- line = NULL;
- current = (*func_it)->address;
- } else {
- return;
- }
-
- while (func || line) {
- // This loop has two invariants that hold at the top.
- //
- // First, at least one of the iterators is not at the end of its
- // sequence, and those that are not refer to the earliest
- // function or line that contains or starts after CURRENT.
- //
- // Note that every byte is in one of four states: it is covered
- // or not covered by a function, and, independently, it is
- // covered or not covered by a line.
- //
- // The second invariant is that CURRENT refers to a byte whose
- // state is different from its predecessor, or it refers to the
- // first byte in the address space. In other words, CURRENT is
- // always the address of a transition.
- //
- // Note that, although each iteration advances CURRENT from one
- // transition address to the next in each iteration, it might
- // not advance the iterators. Suppose we have a function that
- // starts with a line, has a gap, and then a second line, and
- // suppose that we enter an iteration with CURRENT at the end of
- // the first line. The next transition address is the start of
- // the second line, after the gap, so the iteration should
- // advance CURRENT to that point. At the head of that iteration,
- // the invariants require that the line iterator be pointing at
- // the second line. But this is also true at the head of the
- // next. And clearly, the iteration must not change the function
- // iterator. So neither iterator moves.
-
- // Assert the first invariant (see above).
- assert(!func || current < func->address || within(*func, current));
- assert(!line || current < line->address || within(*line, current));
-
- // The next transition after CURRENT.
- Module::Address next_transition;
-
- // Figure out which state we're in, add lines or warn, and compute
- // the next transition address.
- if (func && current >= func->address) {
- if (line && current >= line->address) {
- // Covered by both a line and a function.
- Module::Address func_left = func->size - (current - func->address);
- Module::Address line_left = line->size - (current - line->address);
- // This may overflow, but things work out.
- next_transition = current + std::min(func_left, line_left);
- Module::Line l = *line;
- l.address = current;
- l.size = next_transition - current;
- func->lines.push_back(l);
- last_line_used = line;
- } else {
- // Covered by a function, but no line.
- if (func != last_function_cited) {
- reporter->UncoveredFunction(*func);
- last_function_cited = func;
- }
- if (line && within(*func, line->address))
- next_transition = line->address;
- else
- // If this overflows, we'll catch it below.
- next_transition = func->address + func->size;
- }
- } else {
- if (line && current >= line->address) {
- // Covered by a line, but no function.
- //
- // If GCC emits padding after one function to align the start
- // of the next, then it will attribute the padding
- // instructions to the last source line of function (to reduce
- // the size of the line number info), but omit it from the
- // DW_AT_{low,high}_pc range given in .debug_info (since it
- // costs nothing to be precise there). If we did use at least
- // some of the line we're about to skip, and it ends at the
- // start of the next function, then assume this is what
- // happened, and don't warn.
- if (line != last_line_cited
- && !(func
- && line == last_line_used
- && func->address - line->address == line->size)) {
- reporter->UncoveredLine(*line);
- last_line_cited = line;
- }
- if (func && within(*line, func->address))
- next_transition = func->address;
- else
- // If this overflows, we'll catch it below.
- next_transition = line->address + line->size;
- } else {
- // Covered by neither a function nor a line. By the invariant,
- // both func and line begin after CURRENT. The next transition
- // is the start of the next function or next line, whichever
- // is earliest.
- assert(func || line);
- if (func && line)
- next_transition = std::min(func->address, line->address);
- else if (func)
- next_transition = func->address;
- else
- next_transition = line->address;
- }
- }
-
- // If a function or line abuts the end of the address space, then
- // next_transition may end up being zero, in which case we've completed
- // our pass. Handle that here, instead of trying to deal with it in
- // each place we compute next_transition.
- if (!next_transition)
- break;
-
- // Advance iterators as needed. If lines overlap or functions overlap,
- // then we could go around more than once. We don't worry too much
- // about what result we produce in that case, just as long as we don't
- // hang or crash.
- while (func_it != functions->end()
- && next_transition >= (*func_it)->address
- && !within(**func_it, next_transition))
- func_it++;
- func = (func_it != functions->end()) ? *func_it : NULL;
- while (line_it != lines_.end()
- && next_transition >= line_it->address
- && !within(*line_it, next_transition))
- line_it++;
- line = (line_it != lines_.end()) ? &*line_it : NULL;
-
- // We must make progress.
- assert(next_transition > current);
- current = next_transition;
- }
-}
-
-void DwarfCUToModule::Finish() {
- // Assembly language files have no function data, and that gives us
- // no place to store our line numbers (even though the GNU toolchain
- // will happily produce source line info for assembly language
- // files). To avoid spurious warnings about lines we can't assign
- // to functions, skip CUs in languages that lack functions.
- if (!cu_context_->language->HasFunctions())
- return;
-
- // Read source line info, if we have any.
- if (has_source_line_info_)
- ReadSourceLines(source_line_offset_);
-
- vector<Module::Function *> *functions = &cu_context_->functions;
-
- // Dole out lines to the appropriate functions.
- AssignLinesToFunctions();
-
- // Add our functions, which now have source lines assigned to them,
- // to module_.
- cu_context_->file_context->module_->AddFunctions(functions->begin(),
- functions->end());
-
- // Ownership of the function objects has shifted from cu_context to
- // the Module.
- functions->clear();
-
- cu_context_->file_context->ClearSpecifications();
-}
-
-bool DwarfCUToModule::StartCompilationUnit(uint64 offset,
- uint8 address_size,
- uint8 offset_size,
- uint64 cu_length,
- uint8 dwarf_version) {
- return dwarf_version >= 2;
-}
-
-bool DwarfCUToModule::StartRootDIE(uint64 offset, enum DwarfTag tag) {
- // We don't deal with partial compilation units (the only other tag
- // likely to be used for root DIE).
- return tag == dwarf2reader::DW_TAG_compile_unit;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h
deleted file mode 100644
index fca92710e..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module.h
+++ /dev/null
@@ -1,320 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// Add DWARF debugging information to a Breakpad symbol file. This
-// file defines the DwarfCUToModule class, which accepts parsed DWARF
-// data and populates a google_breakpad::Module with the results; the
-// Module can then write its contents as a Breakpad symbol file.
-
-#ifndef COMMON_LINUX_DWARF_CU_TO_MODULE_H__
-#define COMMON_LINUX_DWARF_CU_TO_MODULE_H__
-
-#include <stdint.h>
-
-#include <string>
-
-#include "common/language.h"
-#include "common/module.h"
-#include "common/dwarf/bytereader.h"
-#include "common/dwarf/dwarf2diehandler.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/scoped_ptr.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using dwarf2reader::DwarfAttribute;
-using dwarf2reader::DwarfForm;
-using dwarf2reader::DwarfLanguage;
-using dwarf2reader::DwarfTag;
-
-// Populate a google_breakpad::Module with DWARF debugging information.
-//
-// An instance of this class can be provided as a handler to a
-// dwarf2reader::DIEDispatcher, which can in turn be a handler for a
-// dwarf2reader::CompilationUnit DWARF parser. The handler uses the results
-// of parsing to populate a google_breakpad::Module with source file,
-// function, and source line information.
-class DwarfCUToModule: public dwarf2reader::RootDIEHandler {
- struct FilePrivate;
- public:
- // Information global to the DWARF-bearing file we are processing,
- // for use by DwarfCUToModule. Each DwarfCUToModule instance deals
- // with a single compilation unit within the file, but information
- // global to the whole file is held here. The client is responsible
- // for filling it in appropriately (except for the 'file_private'
- // field, which the constructor and destructor take care of), and
- // then providing it to the DwarfCUToModule instance for each
- // compilation unit we process in that file. Set HANDLE_INTER_CU_REFS
- // to true to handle debugging symbols with DW_FORM_ref_addr entries.
- class FileContext {
- public:
- FileContext(const string &filename,
- Module *module,
- bool handle_inter_cu_refs);
- ~FileContext();
-
- // Add CONTENTS of size LENGTH to the section map as NAME.
- void AddSectionToSectionMap(const string& name,
- const uint8_t *contents,
- uint64 length);
-
- // Clear the section map for testing.
- void ClearSectionMapForTest();
-
- const dwarf2reader::SectionMap& section_map() const;
-
- private:
- friend class DwarfCUToModule;
-
- // Clears all the Specifications if HANDLE_INTER_CU_REFS_ is false.
- void ClearSpecifications();
-
- // Given an OFFSET and a CU that starts at COMPILATION_UNIT_START, returns
- // true if this is an inter-compilation unit reference that is not being
- // handled.
- bool IsUnhandledInterCUReference(uint64 offset,
- uint64 compilation_unit_start) const;
-
- // The name of this file, for use in error messages.
- const string filename_;
-
- // A map of this file's sections, used for finding other DWARF
- // sections that the .debug_info section may refer to.
- dwarf2reader::SectionMap section_map_;
-
- // The Module to which we're contributing definitions.
- Module *module_;
-
- // True if we are handling references between compilation units.
- const bool handle_inter_cu_refs_;
-
- // Inter-compilation unit data used internally by the handlers.
- scoped_ptr<FilePrivate> file_private_;
- };
-
- // An abstract base class for handlers that handle DWARF line data
- // for DwarfCUToModule. DwarfCUToModule could certainly just use
- // dwarf2reader::LineInfo itself directly, but decoupling things
- // this way makes unit testing a little easier.
- class LineToModuleHandler {
- public:
- LineToModuleHandler() { }
- virtual ~LineToModuleHandler() { }
-
- // Called at the beginning of a new compilation unit, prior to calling
- // ReadProgram(). compilation_dir will indicate the path that the
- // current compilation unit was compiled in, consistent with the
- // DW_AT_comp_dir DIE.
- virtual void StartCompilationUnit(const string& compilation_dir) = 0;
-
- // Populate MODULE and LINES with source file names and code/line
- // mappings, given a pointer to some DWARF line number data
- // PROGRAM, and an overestimate of its size. Add no zero-length
- // lines to LINES.
- virtual void ReadProgram(const uint8_t *program, uint64 length,
- Module *module, vector<Module::Line> *lines) = 0;
- };
-
- // The interface DwarfCUToModule uses to report warnings. The member
- // function definitions for this class write messages to stderr, but
- // you can override them if you'd like to detect or report these
- // conditions yourself.
- class WarningReporter {
- public:
- // Warn about problems in the DWARF file FILENAME, in the
- // compilation unit at OFFSET.
- WarningReporter(const string &filename, uint64 cu_offset)
- : filename_(filename), cu_offset_(cu_offset), printed_cu_header_(false),
- printed_unpaired_header_(false),
- uncovered_warnings_enabled_(false) { }
- virtual ~WarningReporter() { }
-
- // Set the name of the compilation unit we're processing to NAME.
- virtual void SetCUName(const string &name) { cu_name_ = name; }
-
- // Accessor and setter for uncovered_warnings_enabled_.
- // UncoveredFunction and UncoveredLine only report a problem if that is
- // true. By default, these warnings are disabled, because those
- // conditions occur occasionally in healthy code.
- virtual bool uncovered_warnings_enabled() const {
- return uncovered_warnings_enabled_;
- }
- virtual void set_uncovered_warnings_enabled(bool value) {
- uncovered_warnings_enabled_ = value;
- }
-
- // A DW_AT_specification in the DIE at OFFSET refers to a DIE we
- // haven't processed yet, or that wasn't marked as a declaration,
- // at TARGET.
- virtual void UnknownSpecification(uint64 offset, uint64 target);
-
- // A DW_AT_abstract_origin in the DIE at OFFSET refers to a DIE we
- // haven't processed yet, or that wasn't marked as inline, at TARGET.
- virtual void UnknownAbstractOrigin(uint64 offset, uint64 target);
-
- // We were unable to find the DWARF section named SECTION_NAME.
- virtual void MissingSection(const string &section_name);
-
- // The CU's DW_AT_stmt_list offset OFFSET is bogus.
- virtual void BadLineInfoOffset(uint64 offset);
-
- // FUNCTION includes code covered by no line number data.
- virtual void UncoveredFunction(const Module::Function &function);
-
- // Line number NUMBER in LINE_FILE, of length LENGTH, includes code
- // covered by no function.
- virtual void UncoveredLine(const Module::Line &line);
-
- // The DW_TAG_subprogram DIE at OFFSET has no name specified directly
- // in the DIE, nor via a DW_AT_specification or DW_AT_abstract_origin
- // link.
- virtual void UnnamedFunction(uint64 offset);
-
- // __cxa_demangle() failed to demangle INPUT.
- virtual void DemangleError(const string &input, int error);
-
- // The DW_FORM_ref_addr at OFFSET to TARGET was not handled because
- // FilePrivate did not retain the inter-CU specification data.
- virtual void UnhandledInterCUReference(uint64 offset, uint64 target);
-
- uint64 cu_offset() const {
- return cu_offset_;
- }
-
- protected:
- const string filename_;
- const uint64 cu_offset_;
- string cu_name_;
- bool printed_cu_header_;
- bool printed_unpaired_header_;
- bool uncovered_warnings_enabled_;
-
- private:
- // Print a per-CU heading, once.
- void CUHeading();
- // Print an unpaired function/line heading, once.
- void UncoveredHeading();
- };
-
- // Create a DWARF debugging info handler for a compilation unit
- // within FILE_CONTEXT. This uses information received from the
- // dwarf2reader::CompilationUnit DWARF parser to populate
- // FILE_CONTEXT->module. Use LINE_READER to handle the compilation
- // unit's line number data. Use REPORTER to report problems with the
- // data we find.
- DwarfCUToModule(FileContext *file_context,
- LineToModuleHandler *line_reader,
- WarningReporter *reporter);
- ~DwarfCUToModule();
-
- void ProcessAttributeSigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- int64 data);
- void ProcessAttributeUnsigned(enum DwarfAttribute attr,
- enum DwarfForm form,
- uint64 data);
- void ProcessAttributeString(enum DwarfAttribute attr,
- enum DwarfForm form,
- const string &data);
- bool EndAttributes();
- DIEHandler *FindChildHandler(uint64 offset, enum DwarfTag tag);
-
- // Assign all our source Lines to the Functions that cover their
- // addresses, and then add them to module_.
- void Finish();
-
- bool StartCompilationUnit(uint64 offset, uint8 address_size,
- uint8 offset_size, uint64 cu_length,
- uint8 dwarf_version);
- bool StartRootDIE(uint64 offset, enum DwarfTag tag);
-
- private:
- // Used internally by the handler. Full definitions are in
- // dwarf_cu_to_module.cc.
- struct CUContext;
- struct DIEContext;
- struct Specification;
- class GenericDIEHandler;
- class FuncHandler;
- class NamedScopeHandler;
-
- // A map from section offsets to specifications.
- typedef map<uint64, Specification> SpecificationByOffset;
-
- // Set this compilation unit's source language to LANGUAGE.
- void SetLanguage(DwarfLanguage language);
-
- // Read source line information at OFFSET in the .debug_line
- // section. Record source files in module_, but record source lines
- // in lines_; we apportion them to functions in
- // AssignLinesToFunctions.
- void ReadSourceLines(uint64 offset);
-
- // Assign the lines in lines_ to the individual line lists of the
- // functions in functions_. (DWARF line information maps an entire
- // compilation unit at a time, and gives no indication of which
- // lines belong to which functions, beyond their addresses.)
- void AssignLinesToFunctions();
-
- // The only reason cu_context_ and child_context_ are pointers is
- // that we want to keep their definitions private to
- // dwarf_cu_to_module.cc, instead of listing them all here. They are
- // owned by this DwarfCUToModule: the constructor sets them, and the
- // destructor deletes them.
-
- // The handler to use to handle line number data.
- LineToModuleHandler *line_reader_;
-
- // This compilation unit's context.
- scoped_ptr<CUContext> cu_context_;
-
- // A context for our children.
- scoped_ptr<DIEContext> child_context_;
-
- // True if this compilation unit has source line information.
- bool has_source_line_info_;
-
- // The offset of this compilation unit's line number information in
- // the .debug_line section.
- uint64 source_line_offset_;
-
- // The line numbers we have seen thus far. We accumulate these here
- // during parsing. Then, in Finish, we call AssignLinesToFunctions
- // to dole them out to the appropriate functions.
- vector<Module::Line> lines_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_DWARF_CU_TO_MODULE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc
deleted file mode 100644
index 619e90a2e..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_cu_to_module_unittest.cc
+++ /dev/null
@@ -1,1804 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf_cu_to_module.cc: Unit tests for google_breakpad::DwarfCUToModule.
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf_cu_to_module.h"
-#include "common/using_std_string.h"
-
-using std::make_pair;
-using std::vector;
-
-using dwarf2reader::DIEHandler;
-using dwarf2reader::DwarfTag;
-using dwarf2reader::DwarfAttribute;
-using dwarf2reader::DwarfForm;
-using dwarf2reader::DwarfInline;
-using dwarf2reader::RootDIEHandler;
-using google_breakpad::DwarfCUToModule;
-using google_breakpad::Module;
-
-using ::testing::_;
-using ::testing::AtMost;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::Test;
-using ::testing::TestWithParam;
-using ::testing::Values;
-using ::testing::ValuesIn;
-
-// Mock classes.
-
-class MockLineToModuleHandler: public DwarfCUToModule::LineToModuleHandler {
- public:
- MOCK_METHOD1(StartCompilationUnit, void(const string& compilation_dir));
- MOCK_METHOD4(ReadProgram, void(const uint8_t *program, uint64 length,
- Module *module, vector<Module::Line> *lines));
-};
-
-class MockWarningReporter: public DwarfCUToModule::WarningReporter {
- public:
- MockWarningReporter(const string &filename, uint64 cu_offset)
- : DwarfCUToModule::WarningReporter(filename, cu_offset) { }
- MOCK_METHOD1(SetCUName, void(const string &name));
- MOCK_METHOD2(UnknownSpecification, void(uint64 offset, uint64 target));
- MOCK_METHOD2(UnknownAbstractOrigin, void(uint64 offset, uint64 target));
- MOCK_METHOD1(MissingSection, void(const string &section_name));
- MOCK_METHOD1(BadLineInfoOffset, void(uint64 offset));
- MOCK_METHOD1(UncoveredFunction, void(const Module::Function &function));
- MOCK_METHOD1(UncoveredLine, void(const Module::Line &line));
- MOCK_METHOD1(UnnamedFunction, void(uint64 offset));
- MOCK_METHOD2(DemangleError, void(const string &input, int error));
- MOCK_METHOD2(UnhandledInterCUReference, void(uint64 offset, uint64 target));
-};
-
-// A fixture class including all the objects needed to handle a
-// compilation unit, and their entourage. It includes member functions
-// for doing common kinds of setup and tests.
-class CUFixtureBase {
- public:
- // If we have:
- //
- // vector<Module::Line> lines;
- // AppendLinesFunctor appender(lines);
- //
- // then doing:
- //
- // appender(line_program, length, module, line_vector);
- //
- // will append lines to the end of line_vector. We can use this with
- // MockLineToModuleHandler like this:
- //
- // MockLineToModuleHandler l2m;
- // EXPECT_CALL(l2m, ReadProgram(_,_,_,_))
- // .WillOnce(DoAll(Invoke(appender), Return()));
- //
- // in which case calling l2m with some line vector will append lines.
- class AppendLinesFunctor {
- public:
- explicit AppendLinesFunctor(
- const vector<Module::Line> *lines) : lines_(lines) { }
- void operator()(const uint8_t *program, uint64 length,
- Module *module, vector<Module::Line> *lines) {
- lines->insert(lines->end(), lines_->begin(), lines_->end());
- }
- private:
- const vector<Module::Line> *lines_;
- };
-
- CUFixtureBase()
- : module_("module-name", "module-os", "module-arch", "module-id"),
- file_context_("dwarf-filename", &module_, true),
- language_(dwarf2reader::DW_LANG_none),
- language_signed_(false),
- appender_(&lines_),
- reporter_("dwarf-filename", 0xcf8f9bb6443d29b5LL),
- root_handler_(&file_context_, &line_reader_, &reporter_),
- functions_filled_(false) {
- // By default, expect no warnings to be reported, and expect the
- // compilation unit's name to be provided. The test can override
- // these expectations.
- EXPECT_CALL(reporter_, SetCUName("compilation-unit-name")).Times(1);
- EXPECT_CALL(reporter_, UnknownSpecification(_, _)).Times(0);
- EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, _)).Times(0);
- EXPECT_CALL(reporter_, MissingSection(_)).Times(0);
- EXPECT_CALL(reporter_, BadLineInfoOffset(_)).Times(0);
- EXPECT_CALL(reporter_, UncoveredFunction(_)).Times(0);
- EXPECT_CALL(reporter_, UncoveredLine(_)).Times(0);
- EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(0);
- EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(0);
-
- // By default, expect the line program reader not to be invoked. We
- // may override this in StartCU.
- EXPECT_CALL(line_reader_, StartCompilationUnit(_)).Times(0);
- EXPECT_CALL(line_reader_, ReadProgram(_,_,_,_)).Times(0);
-
- // The handler will consult this section map to decide what to
- // pass to our line reader.
- file_context_.AddSectionToSectionMap(".debug_line",
- dummy_line_program_,
- dummy_line_size_);
- }
-
- // Add a line with the given address, size, filename, and line
- // number to the end of the statement list the handler will receive
- // when it invokes its LineToModuleHandler. Call this before calling
- // StartCU.
- void PushLine(Module::Address address, Module::Address size,
- const string &filename, int line_number);
-
- // Use LANGUAGE for the compilation unit. More precisely, arrange
- // for StartCU to pass the compilation unit's root DIE a
- // DW_AT_language attribute whose value is LANGUAGE.
- void SetLanguage(dwarf2reader::DwarfLanguage language) {
- language_ = language;
- }
-
- // If SIGNED true, have StartCU report DW_AT_language as a signed
- // attribute; if false, have it report it as unsigned.
- void SetLanguageSigned(bool is_signed) { language_signed_ = is_signed; }
-
- // Call the handler this.root_handler_'s StartCompilationUnit and
- // StartRootDIE member functions, passing it appropriate attributes as
- // determined by prior calls to PushLine and SetLanguage. Leave
- // this.root_handler_ ready to hear about children: call
- // this.root_handler_.EndAttributes, but not this.root_handler_.Finish.
- void StartCU();
-
- // Have HANDLER process some strange attribute/form/value triples.
- void ProcessStrangeAttributes(dwarf2reader::DIEHandler *handler);
-
- // Start a child DIE of PARENT with the given tag and name. Leave
- // the handler ready to hear about children: call EndAttributes, but
- // not Finish.
- DIEHandler *StartNamedDIE(DIEHandler *parent, DwarfTag tag,
- const string &name);
-
- // Start a child DIE of PARENT with the given tag and a
- // DW_AT_specification attribute whose value is SPECIFICATION. Leave
- // the handler ready to hear about children: call EndAttributes, but
- // not Finish. If NAME is non-zero, use it as the DW_AT_name
- // attribute.
- DIEHandler *StartSpecifiedDIE(DIEHandler *parent, DwarfTag tag,
- uint64 specification, const char *name = NULL);
-
- // Define a function as a child of PARENT with the given name, address, and
- // size. If high_pc_form is DW_FORM_addr then the DW_AT_high_pc attribute
- // will be written as an address; otherwise it will be written as the
- // function's size. Call EndAttributes and Finish; one cannot define
- // children of the defined function's DIE.
- void DefineFunction(DIEHandler *parent, const string &name,
- Module::Address address, Module::Address size,
- const char* mangled_name,
- DwarfForm high_pc_form = dwarf2reader::DW_FORM_addr);
-
- // Create a declaration DIE as a child of PARENT with the given
- // offset, tag and name. If NAME is the empty string, don't provide
- // a DW_AT_name attribute. Call EndAttributes and Finish.
- void DeclarationDIE(DIEHandler *parent, uint64 offset,
- DwarfTag tag, const string &name,
- const string &mangled_name);
-
- // Create a definition DIE as a child of PARENT with the given tag
- // that refers to the declaration DIE at offset SPECIFICATION as its
- // specification. If NAME is non-empty, pass it as the DW_AT_name
- // attribute. If SIZE is non-zero, record ADDRESS and SIZE as
- // low_pc/high_pc attributes.
- void DefinitionDIE(DIEHandler *parent, DwarfTag tag,
- uint64 specification, const string &name,
- Module::Address address = 0, Module::Address size = 0);
-
- // Create an inline DW_TAG_subprogram DIE as a child of PARENT. If
- // SPECIFICATION is non-zero, then the DIE refers to the declaration DIE at
- // offset SPECIFICATION as its specification. If Name is non-empty, pass it
- // as the DW_AT_name attribute.
- void AbstractInstanceDIE(DIEHandler *parent, uint64 offset,
- DwarfInline type, uint64 specification,
- const string &name,
- DwarfForm form = dwarf2reader::DW_FORM_data1);
-
- // Create a DW_TAG_subprogram DIE as a child of PARENT that refers to
- // ORIGIN in its DW_AT_abstract_origin attribute. If NAME is the empty
- // string, don't provide a DW_AT_name attribute.
- void DefineInlineInstanceDIE(DIEHandler *parent, const string &name,
- uint64 origin, Module::Address address,
- Module::Address size);
-
- // The following Test* functions should be called after calling
- // this.root_handler_.Finish. After that point, no further calls
- // should be made on the handler.
-
- // Test that the number of functions defined in the module this.module_ is
- // equal to EXPECTED.
- void TestFunctionCount(size_t expected);
-
- // Test that the I'th function (ordered by address) in the module
- // this.module_ has the given name, address, and size, and that its
- // parameter size is zero.
- void TestFunction(int i, const string &name,
- Module::Address address, Module::Address size);
-
- // Test that the number of source lines owned by the I'th function
- // in the module this.module_ is equal to EXPECTED.
- void TestLineCount(int i, size_t expected);
-
- // Test that the J'th line (ordered by address) of the I'th function
- // (again, by address) has the given address, size, filename, and
- // line number.
- void TestLine(int i, int j, Module::Address address, Module::Address size,
- const string &filename, int number);
-
- // Actual objects under test.
- Module module_;
- DwarfCUToModule::FileContext file_context_;
-
- // If this is not DW_LANG_none, we'll pass it as a DW_AT_language
- // attribute to the compilation unit. This defaults to DW_LANG_none.
- dwarf2reader::DwarfLanguage language_;
-
- // If this is true, report DW_AT_language as a signed value; if false,
- // report it as an unsigned value.
- bool language_signed_;
-
- // If this is not empty, we'll give the CU a DW_AT_comp_dir attribute that
- // indicates the path that this compilation unit was compiled in.
- string compilation_dir_;
-
- // If this is not empty, we'll give the CU a DW_AT_stmt_list
- // attribute that, when passed to line_reader_, adds these lines to the
- // provided lines array.
- vector<Module::Line> lines_;
-
- // Mock line program reader.
- MockLineToModuleHandler line_reader_;
- AppendLinesFunctor appender_;
- static const uint8_t dummy_line_program_[];
- static const size_t dummy_line_size_;
-
- MockWarningReporter reporter_;
- DwarfCUToModule root_handler_;
-
- private:
- // Fill functions_, if we haven't already.
- void FillFunctions();
-
- // If functions_filled_ is true, this is a table of functions we've
- // extracted from module_, sorted by address.
- vector<Module::Function *> functions_;
- // True if we have filled the above vector with this.module_'s function list.
- bool functions_filled_;
-};
-
-const uint8_t CUFixtureBase::dummy_line_program_[] = "lots of fun data";
-const size_t CUFixtureBase::dummy_line_size_ =
- sizeof(CUFixtureBase::dummy_line_program_);
-
-void CUFixtureBase::PushLine(Module::Address address, Module::Address size,
- const string &filename, int line_number) {
- Module::Line l;
- l.address = address;
- l.size = size;
- l.file = module_.FindFile(filename);
- l.number = line_number;
- lines_.push_back(l);
-}
-
-void CUFixtureBase::StartCU() {
- if (!compilation_dir_.empty())
- EXPECT_CALL(line_reader_,
- StartCompilationUnit(compilation_dir_)).Times(1);
-
- // If we have lines, make the line reader expect to be invoked at
- // most once. (Hey, if the handler can pass its tests without
- // bothering to read the line number data, that's great.)
- // Have it add the lines passed to PushLine. Otherwise, leave the
- // initial expectation (no calls) in force.
- if (!lines_.empty())
- EXPECT_CALL(line_reader_,
- ReadProgram(&dummy_line_program_[0], dummy_line_size_,
- &module_, _))
- .Times(AtMost(1))
- .WillOnce(DoAll(Invoke(appender_), Return()));
-
- ASSERT_TRUE(root_handler_
- .StartCompilationUnit(0x51182ec307610b51ULL, 0x81, 0x44,
- 0x4241b4f33720dd5cULL, 3));
- {
- ASSERT_TRUE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL,
- dwarf2reader::DW_TAG_compile_unit));
- }
- root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- "compilation-unit-name");
- if (!compilation_dir_.empty())
- root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_comp_dir,
- dwarf2reader::DW_FORM_strp,
- compilation_dir_);
- if (!lines_.empty())
- root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list,
- dwarf2reader::DW_FORM_ref4,
- 0);
- if (language_ != dwarf2reader::DW_LANG_none) {
- if (language_signed_)
- root_handler_.ProcessAttributeSigned(dwarf2reader::DW_AT_language,
- dwarf2reader::DW_FORM_sdata,
- language_);
- else
- root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_language,
- dwarf2reader::DW_FORM_udata,
- language_);
- }
- ASSERT_TRUE(root_handler_.EndAttributes());
-}
-
-void CUFixtureBase::ProcessStrangeAttributes(
- dwarf2reader::DIEHandler *handler) {
- handler->ProcessAttributeUnsigned((DwarfAttribute) 0xf560dead,
- (DwarfForm) 0x4106e4db,
- 0xa592571997facda1ULL);
- handler->ProcessAttributeSigned((DwarfAttribute) 0x85380095,
- (DwarfForm) 0x0f16fe87,
- 0x12602a4e3bf1f446LL);
- handler->ProcessAttributeReference((DwarfAttribute) 0xf7f7480f,
- (DwarfForm) 0x829e038a,
- 0x50fddef44734fdecULL);
- static const uint8_t buffer[10] = "frobynode";
- handler->ProcessAttributeBuffer((DwarfAttribute) 0xa55ffb51,
- (DwarfForm) 0x2f43b041,
- buffer, sizeof(buffer));
- handler->ProcessAttributeString((DwarfAttribute) 0x2f43b041,
- (DwarfForm) 0x895ffa23,
- "strange string");
-}
-
-DIEHandler *CUFixtureBase::StartNamedDIE(DIEHandler *parent,
- DwarfTag tag,
- const string &name) {
- dwarf2reader::DIEHandler *handler
- = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag);
- if (!handler)
- return NULL;
- handler->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- ProcessStrangeAttributes(handler);
- if (!handler->EndAttributes()) {
- handler->Finish();
- delete handler;
- return NULL;
- }
-
- return handler;
-}
-
-DIEHandler *CUFixtureBase::StartSpecifiedDIE(DIEHandler *parent,
- DwarfTag tag,
- uint64 specification,
- const char *name) {
- dwarf2reader::DIEHandler *handler
- = parent->FindChildHandler(0x8f4c783c0467c989ULL, tag);
- if (!handler)
- return NULL;
- if (name)
- handler->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- handler->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
- dwarf2reader::DW_FORM_ref4,
- specification);
- if (!handler->EndAttributes()) {
- handler->Finish();
- delete handler;
- return NULL;
- }
-
- return handler;
-}
-
-void CUFixtureBase::DefineFunction(dwarf2reader::DIEHandler *parent,
- const string &name, Module::Address address,
- Module::Address size,
- const char* mangled_name,
- DwarfForm high_pc_form) {
- dwarf2reader::DIEHandler *func
- = parent->FindChildHandler(0xe34797c7e68590a8LL,
- dwarf2reader::DW_TAG_subprogram);
- ASSERT_TRUE(func != NULL);
- func->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr,
- address);
-
- Module::Address high_pc = size;
- if (high_pc_form == dwarf2reader::DW_FORM_addr) {
- high_pc += address;
- }
- func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
- high_pc_form,
- high_pc);
-
- if (mangled_name)
- func->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
- dwarf2reader::DW_FORM_strp,
- mangled_name);
-
- ProcessStrangeAttributes(func);
- EXPECT_TRUE(func->EndAttributes());
- func->Finish();
- delete func;
-}
-
-void CUFixtureBase::DeclarationDIE(DIEHandler *parent, uint64 offset,
- DwarfTag tag,
- const string &name,
- const string &mangled_name) {
- dwarf2reader::DIEHandler *die = parent->FindChildHandler(offset, tag);
- ASSERT_TRUE(die != NULL);
- if (!name.empty())
- die->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- if (!mangled_name.empty())
- die->ProcessAttributeString(dwarf2reader::DW_AT_MIPS_linkage_name,
- dwarf2reader::DW_FORM_strp,
- mangled_name);
-
- die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_declaration,
- dwarf2reader::DW_FORM_flag,
- 1);
- EXPECT_TRUE(die->EndAttributes());
- die->Finish();
- delete die;
-}
-
-void CUFixtureBase::DefinitionDIE(DIEHandler *parent,
- DwarfTag tag,
- uint64 specification,
- const string &name,
- Module::Address address,
- Module::Address size) {
- dwarf2reader::DIEHandler *die
- = parent->FindChildHandler(0x6ccfea031a9e6cc9ULL, tag);
- ASSERT_TRUE(die != NULL);
- die->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
- dwarf2reader::DW_FORM_ref4,
- specification);
- if (!name.empty())
- die->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- if (size) {
- die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr,
- address);
- die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
- dwarf2reader::DW_FORM_addr,
- address + size);
- }
- EXPECT_TRUE(die->EndAttributes());
- die->Finish();
- delete die;
-}
-
-void CUFixtureBase::AbstractInstanceDIE(DIEHandler *parent,
- uint64 offset,
- DwarfInline type,
- uint64 specification,
- const string &name,
- DwarfForm form) {
- dwarf2reader::DIEHandler *die
- = parent->FindChildHandler(offset, dwarf2reader::DW_TAG_subprogram);
- ASSERT_TRUE(die != NULL);
- if (specification != 0ULL)
- die->ProcessAttributeReference(dwarf2reader::DW_AT_specification,
- dwarf2reader::DW_FORM_ref4,
- specification);
- if (form == dwarf2reader::DW_FORM_sdata) {
- die->ProcessAttributeSigned(dwarf2reader::DW_AT_inline, form, type);
- } else {
- die->ProcessAttributeUnsigned(dwarf2reader::DW_AT_inline, form, type);
- }
- if (!name.empty())
- die->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
-
- EXPECT_TRUE(die->EndAttributes());
- die->Finish();
- delete die;
-}
-
-void CUFixtureBase::DefineInlineInstanceDIE(DIEHandler *parent,
- const string &name,
- uint64 origin,
- Module::Address address,
- Module::Address size) {
- dwarf2reader::DIEHandler *func
- = parent->FindChildHandler(0x11c70f94c6e87ccdLL,
- dwarf2reader::DW_TAG_subprogram);
- ASSERT_TRUE(func != NULL);
- if (!name.empty()) {
- func->ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- name);
- }
- func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_low_pc,
- dwarf2reader::DW_FORM_addr,
- address);
- func->ProcessAttributeUnsigned(dwarf2reader::DW_AT_high_pc,
- dwarf2reader::DW_FORM_addr,
- address + size);
- func->ProcessAttributeReference(dwarf2reader::DW_AT_abstract_origin,
- dwarf2reader::DW_FORM_ref4,
- origin);
- ProcessStrangeAttributes(func);
- EXPECT_TRUE(func->EndAttributes());
- func->Finish();
- delete func;
-}
-
-void CUFixtureBase::FillFunctions() {
- if (functions_filled_)
- return;
- module_.GetFunctions(&functions_, functions_.end());
- sort(functions_.begin(), functions_.end(),
- Module::Function::CompareByAddress);
- functions_filled_ = true;
-}
-
-void CUFixtureBase::TestFunctionCount(size_t expected) {
- FillFunctions();
- ASSERT_EQ(expected, functions_.size());
-}
-
-void CUFixtureBase::TestFunction(int i, const string &name,
- Module::Address address,
- Module::Address size) {
- FillFunctions();
- ASSERT_LT((size_t) i, functions_.size());
-
- Module::Function *function = functions_[i];
- EXPECT_EQ(name, function->name);
- EXPECT_EQ(address, function->address);
- EXPECT_EQ(size, function->size);
- EXPECT_EQ(0U, function->parameter_size);
-}
-
-void CUFixtureBase::TestLineCount(int i, size_t expected) {
- FillFunctions();
- ASSERT_LT((size_t) i, functions_.size());
-
- ASSERT_EQ(expected, functions_[i]->lines.size());
-}
-
-void CUFixtureBase::TestLine(int i, int j,
- Module::Address address, Module::Address size,
- const string &filename, int number) {
- FillFunctions();
- ASSERT_LT((size_t) i, functions_.size());
- ASSERT_LT((size_t) j, functions_[i]->lines.size());
-
- Module::Line *line = &functions_[i]->lines[j];
- EXPECT_EQ(address, line->address);
- EXPECT_EQ(size, line->size);
- EXPECT_EQ(filename, line->file->name.c_str());
- EXPECT_EQ(number, line->number);
-}
-
-// Include caller locations for our test subroutines.
-#define TRACE(call) do { SCOPED_TRACE("called from here"); call; } while (0)
-#define PushLine(a,b,c,d) TRACE(PushLine((a),(b),(c),(d)))
-#define SetLanguage(a) TRACE(SetLanguage(a))
-#define StartCU() TRACE(StartCU())
-#define DefineFunction(a,b,c,d,e) TRACE(DefineFunction((a),(b),(c),(d),(e)))
-// (DefineFunction) instead of DefineFunction to avoid macro expansion.
-#define DefineFunction6(a,b,c,d,e,f) \
- TRACE((DefineFunction)((a),(b),(c),(d),(e),(f)))
-#define DeclarationDIE(a,b,c,d,e) TRACE(DeclarationDIE((a),(b),(c),(d),(e)))
-#define DefinitionDIE(a,b,c,d,e,f) \
- TRACE(DefinitionDIE((a),(b),(c),(d),(e),(f)))
-#define TestFunctionCount(a) TRACE(TestFunctionCount(a))
-#define TestFunction(a,b,c,d) TRACE(TestFunction((a),(b),(c),(d)))
-#define TestLineCount(a,b) TRACE(TestLineCount((a),(b)))
-#define TestLine(a,b,c,d,e,f) TRACE(TestLine((a),(b),(c),(d),(e),(f)))
-
-class SimpleCU: public CUFixtureBase, public Test {
-};
-
-TEST_F(SimpleCU, CompilationDir) {
- compilation_dir_ = "/src/build/";
-
- StartCU();
- root_handler_.Finish();
-}
-
-TEST_F(SimpleCU, OneFunc) {
- PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
-
- StartCU();
- DefineFunction(&root_handler_, "function1",
- 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
- TestLineCount(0, 1);
- TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file",
- 246571772);
-}
-
-// As above, only DW_AT_high_pc is a length rather than an address.
-TEST_F(SimpleCU, OneFuncHighPcIsLength) {
- PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
-
- StartCU();
- DefineFunction6(&root_handler_, "function1",
- 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, NULL,
- dwarf2reader::DW_FORM_udata);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "function1", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
- TestLineCount(0, 1);
- TestLine(0, 0, 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file",
- 246571772);
-}
-
-TEST_F(SimpleCU, MangledName) {
- PushLine(0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "line-file", 246571772);
-
- StartCU();
- DefineFunction(&root_handler_, "function1",
- 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL, "_ZN1n1fEi");
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "n::f(int)", 0x938cf8c07def4d34ULL, 0x55592d727f6cd01fLL);
-}
-
-TEST_F(SimpleCU, IrrelevantRootChildren) {
- StartCU();
- EXPECT_FALSE(root_handler_
- .FindChildHandler(0x7db32bff4e2dcfb1ULL,
- dwarf2reader::DW_TAG_lexical_block));
-}
-
-TEST_F(SimpleCU, IrrelevantNamedScopeChildren) {
- StartCU();
- DIEHandler *class_A_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
- EXPECT_TRUE(class_A_handler != NULL);
- EXPECT_FALSE(class_A_handler
- ->FindChildHandler(0x02e55999b865e4e9ULL,
- dwarf2reader::DW_TAG_lexical_block));
- delete class_A_handler;
-}
-
-// Verify that FileContexts can safely be deleted unused.
-TEST_F(SimpleCU, UnusedFileContext) {
- Module m("module-name", "module-os", "module-arch", "module-id");
- DwarfCUToModule::FileContext fc("dwarf-filename", &m, true);
-
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-}
-
-TEST_F(SimpleCU, InlineFunction) {
- PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
-
- StartCU();
- AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
- dwarf2reader::DW_INL_inlined, 0, "inline-name");
- DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "inline-name",
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
-}
-
-TEST_F(SimpleCU, InlineFunctionSignedAttribute) {
- PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
-
- StartCU();
- AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
- dwarf2reader::DW_INL_inlined, 0, "inline-name",
- dwarf2reader::DW_FORM_sdata);
- DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "inline-name",
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
-}
-
-// Any DIE with an DW_AT_inline attribute can be cited by
-// DW_AT_abstract_origin attributes --- even if the value of the
-// DW_AT_inline attribute is DW_INL_not_inlined.
-TEST_F(SimpleCU, AbstractOriginNotInlined) {
- PushLine(0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL, "line-file", 6111581);
-
- StartCU();
- AbstractInstanceDIE(&root_handler_, 0x93e9cdad52826b39ULL,
- dwarf2reader::DW_INL_not_inlined, 0, "abstract-instance");
- DefineInlineInstanceDIE(&root_handler_, "", 0x93e9cdad52826b39ULL,
- 0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "abstract-instance",
- 0x2805c4531be6ca0eULL, 0x686b52155a8d4d2cULL);
-}
-
-TEST_F(SimpleCU, UnknownAbstractOrigin) {
- EXPECT_CALL(reporter_, UnknownAbstractOrigin(_, 1ULL)).WillOnce(Return());
- EXPECT_CALL(reporter_, UnnamedFunction(0x11c70f94c6e87ccdLL))
- .WillOnce(Return());
- PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
-
- StartCU();
- AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
- dwarf2reader::DW_INL_inlined, 0, "inline-name");
- DefineInlineInstanceDIE(&root_handler_, "", 1ULL,
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "<name omitted>",
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
-}
-
-TEST_F(SimpleCU, UnnamedFunction) {
- EXPECT_CALL(reporter_, UnnamedFunction(0xe34797c7e68590a8LL))
- .WillOnce(Return());
- PushLine(0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, "line-file", 14044850);
-
- StartCU();
- DefineFunction(&root_handler_, "",
- 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "<name omitted>",
- 0x72b80e41a0ac1d40ULL, 0x537174f231ee181cULL);
-}
-
-// An address range.
-struct Range {
- Module::Address start, end;
-};
-
-// Test data for pairing functions and lines.
-struct Situation {
- // Two function intervals, and two line intervals.
- Range functions[2], lines[2];
-
- // The number of lines we expect to be assigned to each of the
- // functions, and the address ranges.
- int paired_count[2];
- Range paired[2][2];
-
- // The number of functions that are not entirely covered by lines,
- // and vice versa.
- int uncovered_functions, uncovered_lines;
-};
-
-#define PAIRING(func1_start, func1_end, func2_start, func2_end, \
- line1_start, line1_end, line2_start, line2_end, \
- func1_num_lines, func2_num_lines, \
- func1_line1_start, func1_line1_end, \
- func1_line2_start, func1_line2_end, \
- func2_line1_start, func2_line1_end, \
- func2_line2_start, func2_line2_end, \
- uncovered_functions, uncovered_lines) \
- { { { func1_start, func1_end }, { func2_start, func2_end } }, \
- { { line1_start, line1_end }, { line2_start, line2_end } }, \
- { func1_num_lines, func2_num_lines }, \
- { { { func1_line1_start, func1_line1_end }, \
- { func1_line2_start, func1_line2_end } }, \
- { { func2_line1_start, func2_line1_end }, \
- { func2_line2_start, func2_line2_end } } }, \
- uncovered_functions, uncovered_lines },
-
-Situation situations[] = {
-#include "common/testdata/func-line-pairing.h"
-};
-
-#undef PAIRING
-
-class FuncLinePairing: public CUFixtureBase,
- public TestWithParam<Situation> { };
-
-INSTANTIATE_TEST_CASE_P(AllSituations, FuncLinePairing,
- ValuesIn(situations));
-
-TEST_P(FuncLinePairing, Pairing) {
- const Situation &s = GetParam();
- PushLine(s.lines[0].start,
- s.lines[0].end - s.lines[0].start,
- "line-file", 67636963);
- PushLine(s.lines[1].start,
- s.lines[1].end - s.lines[1].start,
- "line-file", 67636963);
- if (s.uncovered_functions)
- EXPECT_CALL(reporter_, UncoveredFunction(_))
- .Times(s.uncovered_functions)
- .WillRepeatedly(Return());
- if (s.uncovered_lines)
- EXPECT_CALL(reporter_, UncoveredLine(_))
- .Times(s.uncovered_lines)
- .WillRepeatedly(Return());
-
- StartCU();
- DefineFunction(&root_handler_, "function1",
- s.functions[0].start,
- s.functions[0].end - s.functions[0].start, NULL);
- DefineFunction(&root_handler_, "function2",
- s.functions[1].start,
- s.functions[1].end - s.functions[1].start, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "function1",
- s.functions[0].start,
- s.functions[0].end - s.functions[0].start);
- TestLineCount(0, s.paired_count[0]);
- for (int i = 0; i < s.paired_count[0]; i++)
- TestLine(0, i, s.paired[0][i].start,
- s.paired[0][i].end - s.paired[0][i].start,
- "line-file", 67636963);
- TestFunction(1, "function2",
- s.functions[1].start,
- s.functions[1].end - s.functions[1].start);
- TestLineCount(1, s.paired_count[1]);
- for (int i = 0; i < s.paired_count[1]; i++)
- TestLine(1, i, s.paired[1][i].start,
- s.paired[1][i].end - s.paired[1][i].start,
- "line-file", 67636963);
-}
-
-TEST_F(FuncLinePairing, EmptyCU) {
- StartCU();
- root_handler_.Finish();
-
- TestFunctionCount(0);
-}
-
-TEST_F(FuncLinePairing, LinesNoFuncs) {
- PushLine(40, 2, "line-file", 82485646);
- EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
-
- StartCU();
- root_handler_.Finish();
-
- TestFunctionCount(0);
-}
-
-TEST_F(FuncLinePairing, FuncsNoLines) {
- EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
-
- StartCU();
- DefineFunction(&root_handler_, "function1", 0x127da12ffcf5c51fULL, 0x1000U,
- NULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "function1", 0x127da12ffcf5c51fULL, 0x1000U);
-}
-
-TEST_F(FuncLinePairing, GapThenFunction) {
- PushLine(20, 2, "line-file-2", 174314698);
- PushLine(10, 2, "line-file-1", 263008005);
-
- StartCU();
- DefineFunction(&root_handler_, "function1", 10, 2, NULL);
- DefineFunction(&root_handler_, "function2", 20, 2, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "function1", 10, 2);
- TestLineCount(0, 1);
- TestLine(0, 0, 10, 2, "line-file-1", 263008005);
- TestFunction(1, "function2", 20, 2);
- TestLineCount(1, 1);
- TestLine(1, 0, 20, 2, "line-file-2", 174314698);
-}
-
-// If GCC emits padding after one function to align the start of
-// the next, then it will attribute the padding instructions to
-// the last source line of function (to reduce the size of the
-// line number info), but omit it from the DW_AT_{low,high}_pc
-// range given in .debug_info (since it costs nothing to be
-// precise there). If we did use at least some of the line
-// we're about to skip, then assume this is what happened, and
-// don't warn.
-TEST_F(FuncLinePairing, GCCAlignmentStretch) {
- PushLine(10, 10, "line-file", 63351048);
- PushLine(20, 10, "line-file", 61661044);
-
- StartCU();
- DefineFunction(&root_handler_, "function1", 10, 5, NULL);
- // five-byte gap between functions, covered by line 63351048.
- // This should not elicit a warning.
- DefineFunction(&root_handler_, "function2", 20, 10, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "function1", 10, 5);
- TestLineCount(0, 1);
- TestLine(0, 0, 10, 5, "line-file", 63351048);
- TestFunction(1, "function2", 20, 10);
- TestLineCount(1, 1);
- TestLine(1, 0, 20, 10, "line-file", 61661044);
-}
-
-// Unfortunately, neither the DWARF parser's handler interface nor the
-// DIEHandler interface is capable of expressing a function that abuts
-// the end of the address space: the high_pc value looks like zero.
-
-TEST_F(FuncLinePairing, LineAtEndOfAddressSpace) {
- PushLine(0xfffffffffffffff0ULL, 16, "line-file", 63351048);
- EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
-
- StartCU();
- DefineFunction(&root_handler_, "function1", 0xfffffffffffffff0ULL, 6, NULL);
- DefineFunction(&root_handler_, "function2", 0xfffffffffffffffaULL, 5, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "function1", 0xfffffffffffffff0ULL, 6);
- TestLineCount(0, 1);
- TestLine(0, 0, 0xfffffffffffffff0ULL, 6, "line-file", 63351048);
- TestFunction(1, "function2", 0xfffffffffffffffaULL, 5);
- TestLineCount(1, 1);
- TestLine(1, 0, 0xfffffffffffffffaULL, 5, "line-file", 63351048);
-}
-
-// A function with more than one uncovered area should only be warned
-// about once.
-TEST_F(FuncLinePairing, WarnOnceFunc) {
- PushLine(20, 1, "line-file-2", 262951329);
- PushLine(11, 1, "line-file-1", 219964021);
- EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
-
- StartCU();
- DefineFunction(&root_handler_, "function", 10, 11, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "function", 10, 11);
- TestLineCount(0, 2);
- TestLine(0, 0, 11, 1, "line-file-1", 219964021);
- TestLine(0, 1, 20, 1, "line-file-2", 262951329);
-}
-
-// A line with more than one uncovered area should only be warned
-// about once.
-TEST_F(FuncLinePairing, WarnOnceLine) {
- PushLine(10, 20, "filename1", 118581871);
- EXPECT_CALL(reporter_, UncoveredLine(_)).WillOnce(Return());
-
- StartCU();
- DefineFunction(&root_handler_, "function1", 11, 1, NULL);
- DefineFunction(&root_handler_, "function2", 13, 1, NULL);
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "function1", 11, 1);
- TestLineCount(0, 1);
- TestLine(0, 0, 11, 1, "filename1", 118581871);
- TestFunction(1, "function2", 13, 1);
- TestLineCount(1, 1);
- TestLine(1, 0, 13, 1, "filename1", 118581871);
-}
-
-class CXXQualifiedNames: public CUFixtureBase,
- public TestWithParam<DwarfTag> { };
-
-INSTANTIATE_TEST_CASE_P(VersusEnclosures, CXXQualifiedNames,
- Values(dwarf2reader::DW_TAG_class_type,
- dwarf2reader::DW_TAG_structure_type,
- dwarf2reader::DW_TAG_union_type,
- dwarf2reader::DW_TAG_namespace));
-
-TEST_P(CXXQualifiedNames, TwoFunctions) {
- DwarfTag tag = GetParam();
-
- SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
- PushLine(10, 1, "filename1", 69819327);
- PushLine(20, 1, "filename2", 95115701);
-
- StartCU();
- DIEHandler *enclosure_handler = StartNamedDIE(&root_handler_, tag,
- "Enclosure");
- EXPECT_TRUE(enclosure_handler != NULL);
- DefineFunction(enclosure_handler, "func_B", 10, 1, NULL);
- DefineFunction(enclosure_handler, "func_C", 20, 1, NULL);
- enclosure_handler->Finish();
- delete enclosure_handler;
- root_handler_.Finish();
-
- TestFunctionCount(2);
- TestFunction(0, "Enclosure::func_B", 10, 1);
- TestFunction(1, "Enclosure::func_C", 20, 1);
-}
-
-TEST_P(CXXQualifiedNames, FuncInEnclosureInNamespace) {
- DwarfTag tag = GetParam();
-
- SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
- PushLine(10, 1, "line-file", 69819327);
-
- StartCU();
- DIEHandler *namespace_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- "Namespace");
- EXPECT_TRUE(namespace_handler != NULL);
- DIEHandler *enclosure_handler = StartNamedDIE(namespace_handler, tag,
- "Enclosure");
- EXPECT_TRUE(enclosure_handler != NULL);
- DefineFunction(enclosure_handler, "function", 10, 1, NULL);
- enclosure_handler->Finish();
- delete enclosure_handler;
- namespace_handler->Finish();
- delete namespace_handler;
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "Namespace::Enclosure::function", 10, 1);
-}
-
-TEST_F(CXXQualifiedNames, FunctionInClassInStructInNamespace) {
- SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
- PushLine(10, 1, "filename1", 69819327);
-
- StartCU();
- DIEHandler *namespace_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- "namespace_A");
- EXPECT_TRUE(namespace_handler != NULL);
- DIEHandler *struct_handler
- = StartNamedDIE(namespace_handler, dwarf2reader::DW_TAG_structure_type,
- "struct_B");
- EXPECT_TRUE(struct_handler != NULL);
- DIEHandler *class_handler
- = StartNamedDIE(struct_handler, dwarf2reader::DW_TAG_class_type,
- "class_C");
- DefineFunction(class_handler, "function_D", 10, 1, NULL);
- class_handler->Finish();
- delete class_handler;
- struct_handler->Finish();
- delete struct_handler;
- namespace_handler->Finish();
- delete namespace_handler;
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "namespace_A::struct_B::class_C::function_D", 10, 1);
-}
-
-struct LanguageAndQualifiedName {
- dwarf2reader::DwarfLanguage language;
- const char *name;
-};
-
-const LanguageAndQualifiedName LanguageAndQualifiedNameCases[] = {
- { dwarf2reader::DW_LANG_none, "class_A::function_B" },
- { dwarf2reader::DW_LANG_C, "class_A::function_B" },
- { dwarf2reader::DW_LANG_C89, "class_A::function_B" },
- { dwarf2reader::DW_LANG_C99, "class_A::function_B" },
- { dwarf2reader::DW_LANG_C_plus_plus, "class_A::function_B" },
- { dwarf2reader::DW_LANG_Java, "class_A.function_B" },
- { dwarf2reader::DW_LANG_Cobol74, "class_A::function_B" },
- { dwarf2reader::DW_LANG_Mips_Assembler, NULL }
-};
-
-class QualifiedForLanguage
- : public CUFixtureBase,
- public TestWithParam<LanguageAndQualifiedName> { };
-
-INSTANTIATE_TEST_CASE_P(LanguageAndQualifiedName, QualifiedForLanguage,
- ValuesIn(LanguageAndQualifiedNameCases));
-
-TEST_P(QualifiedForLanguage, MemberFunction) {
- const LanguageAndQualifiedName &param = GetParam();
-
- PushLine(10, 1, "line-file", 212966758);
- SetLanguage(param.language);
-
- StartCU();
- DIEHandler *class_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- "class_A");
- DefineFunction(class_handler, "function_B", 10, 1, NULL);
- class_handler->Finish();
- delete class_handler;
- root_handler_.Finish();
-
- if (param.name) {
- TestFunctionCount(1);
- TestFunction(0, param.name, 10, 1);
- } else {
- TestFunctionCount(0);
- }
-}
-
-TEST_P(QualifiedForLanguage, MemberFunctionSignedLanguage) {
- const LanguageAndQualifiedName &param = GetParam();
-
- PushLine(10, 1, "line-file", 212966758);
- SetLanguage(param.language);
- SetLanguageSigned(true);
-
- StartCU();
- DIEHandler *class_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- "class_A");
- DefineFunction(class_handler, "function_B", 10, 1, NULL);
- class_handler->Finish();
- delete class_handler;
- root_handler_.Finish();
-
- if (param.name) {
- TestFunctionCount(1);
- TestFunction(0, param.name, 10, 1);
- } else {
- TestFunctionCount(0);
- }
-}
-
-class Specifications: public CUFixtureBase, public Test { };
-
-TEST_F(Specifications, Function) {
- PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
- dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0xcd3c51b946fb1eeeLL, "",
- 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "declaration-name",
- 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
-}
-
-TEST_F(Specifications, MangledName) {
- PushLine(0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL, "line-file", 54883661);
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
- dwarf2reader::DW_TAG_subprogram, "declaration-name",
- "_ZN1C1fEi");
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0xcd3c51b946fb1eeeLL, "",
- 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "C::f(int)",
- 0x93cd3dfc1aa10097ULL, 0x0397d47a0b4ca0d4ULL);
-}
-
-TEST_F(Specifications, MemberFunction) {
- PushLine(0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL, "line-file", 18116691);
-
- StartCU();
- DIEHandler *class_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type, "class_A");
- DeclarationDIE(class_handler, 0x7d83028c431406e8ULL,
- dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
- class_handler->Finish();
- delete class_handler;
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0x7d83028c431406e8ULL, "",
- 0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "class_A::declaration-name",
- 0x3341a248634e7170ULL, 0x5f6938ee5553b953ULL);
-}
-
-// This case should gather the name from both the definition and the
-// declaration's parent.
-TEST_F(Specifications, FunctionDeclarationParent) {
- PushLine(0x463c9ddf405be227ULL, 0x6a47774af5049680ULL, "line-file", 70254922);
-
- StartCU();
- {
- DIEHandler *class_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- "class_A");
- ASSERT_TRUE(class_handler != NULL);
- DeclarationDIE(class_handler, 0x0e0e877c8404544aULL,
- dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
- class_handler->Finish();
- delete class_handler;
- }
-
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0x0e0e877c8404544aULL, "definition-name",
- 0x463c9ddf405be227ULL, 0x6a47774af5049680ULL);
-
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "class_A::definition-name",
- 0x463c9ddf405be227ULL, 0x6a47774af5049680ULL);
-}
-
-// Named scopes should also gather enclosing name components from
-// their declarations.
-TEST_F(Specifications, NamedScopeDeclarationParent) {
- PushLine(0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, "line-file", 77392604);
-
- StartCU();
- {
- DIEHandler *space_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- "space_A");
- ASSERT_TRUE(space_handler != NULL);
- DeclarationDIE(space_handler, 0x419bb1d12f9a73a2ULL,
- dwarf2reader::DW_TAG_class_type, "class-declaration-name",
- "");
- space_handler->Finish();
- delete space_handler;
- }
-
- {
- DIEHandler *class_handler
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- 0x419bb1d12f9a73a2ULL, "class-definition-name");
- ASSERT_TRUE(class_handler != NULL);
- DefineFunction(class_handler, "function",
- 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL, NULL);
- class_handler->Finish();
- delete class_handler;
- }
-
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "space_A::class-definition-name::function",
- 0x5d13433d0df13d00ULL, 0x48ebebe5ade2cab4ULL);
-}
-
-// This test recreates bug 364.
-TEST_F(Specifications, InlineFunction) {
- PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xcd3c51b946fb1eeeLL,
- dwarf2reader::DW_TAG_subprogram, "inline-name", "");
- AbstractInstanceDIE(&root_handler_, 0x1e8dac5d507ed7abULL,
- dwarf2reader::DW_INL_inlined, 0xcd3c51b946fb1eeeLL, "");
- DefineInlineInstanceDIE(&root_handler_, "", 0x1e8dac5d507ed7abULL,
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "inline-name",
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
-}
-
-// An inline function in a namespace should correctly derive its
-// name from its abstract origin, and not just the namespace name.
-TEST_F(Specifications, InlineFunctionInNamespace) {
- PushLine(0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL, "line-file", 75173118);
-
- StartCU();
- DIEHandler* space_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- "Namespace");
- ASSERT_TRUE(space_handler != NULL);
- AbstractInstanceDIE(space_handler, 0x1e8dac5d507ed7abULL,
- dwarf2reader::DW_INL_inlined, 0LL, "func-name");
- DefineInlineInstanceDIE(space_handler, "", 0x1e8dac5d507ed7abULL,
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
- space_handler->Finish();
- delete space_handler;
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "Namespace::func-name",
- 0x1758a0f941b71efbULL, 0x1cf154f1f545e146ULL);
-}
-
-// Check name construction for a long chain containing each combination of:
-// - struct, union, class, namespace
-// - direct and definition
-TEST_F(Specifications, LongChain) {
- PushLine(0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL, "line-file", 21192926);
- SetLanguage(dwarf2reader::DW_LANG_C_plus_plus);
-
- StartCU();
- // The structure we're building here is:
- // space_A full definition
- // space_B declaration
- // space_B definition
- // struct_C full definition
- // struct_D declaration
- // struct_D definition
- // union_E full definition
- // union_F declaration
- // union_F definition
- // class_G full definition
- // class_H declaration
- // class_H definition
- // func_I declaration
- // func_I definition
- //
- // So:
- // - space_A, struct_C, union_E, and class_G don't use specifications;
- // - space_B, struct_D, union_F, and class_H do.
- // - func_I uses a specification.
- //
- // The full name for func_I is thus:
- //
- // space_A::space_B::struct_C::struct_D::union_E::union_F::
- // class_G::class_H::func_I
- {
- DIEHandler *space_A_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- "space_A");
- DeclarationDIE(space_A_handler, 0x2e111126496596e2ULL,
- dwarf2reader::DW_TAG_namespace, "space_B", "");
- space_A_handler->Finish();
- delete space_A_handler;
- }
-
- {
- DIEHandler *space_B_handler
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_namespace,
- 0x2e111126496596e2ULL);
- DIEHandler *struct_C_handler
- = StartNamedDIE(space_B_handler, dwarf2reader::DW_TAG_structure_type,
- "struct_C");
- DeclarationDIE(struct_C_handler, 0x20cd423bf2a25a4cULL,
- dwarf2reader::DW_TAG_structure_type, "struct_D", "");
- struct_C_handler->Finish();
- delete struct_C_handler;
- space_B_handler->Finish();
- delete space_B_handler;
- }
-
- {
- DIEHandler *struct_D_handler
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_structure_type,
- 0x20cd423bf2a25a4cULL);
- DIEHandler *union_E_handler
- = StartNamedDIE(struct_D_handler, dwarf2reader::DW_TAG_union_type,
- "union_E");
- DeclarationDIE(union_E_handler, 0xe25c84805aa58c32ULL,
- dwarf2reader::DW_TAG_union_type, "union_F", "");
- union_E_handler->Finish();
- delete union_E_handler;
- struct_D_handler->Finish();
- delete struct_D_handler;
- }
-
- {
- DIEHandler *union_F_handler
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_union_type,
- 0xe25c84805aa58c32ULL);
- DIEHandler *class_G_handler
- = StartNamedDIE(union_F_handler, dwarf2reader::DW_TAG_class_type,
- "class_G");
- DeclarationDIE(class_G_handler, 0xb70d960dcc173b6eULL,
- dwarf2reader::DW_TAG_class_type, "class_H", "");
- class_G_handler->Finish();
- delete class_G_handler;
- union_F_handler->Finish();
- delete union_F_handler;
- }
-
- {
- DIEHandler *class_H_handler
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- 0xb70d960dcc173b6eULL);
- DeclarationDIE(class_H_handler, 0x27ff829e3bf69f37ULL,
- dwarf2reader::DW_TAG_subprogram, "func_I", "");
- class_H_handler->Finish();
- delete class_H_handler;
- }
-
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0x27ff829e3bf69f37ULL, "",
- 0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "space_A::space_B::struct_C::struct_D::union_E::union_F"
- "::class_G::class_H::func_I",
- 0x5a0dd6bb85db754cULL, 0x3bccb213d08c7fd3ULL);
-}
-
-TEST_F(Specifications, InterCU) {
- Module m("module-name", "module-os", "module-arch", "module-id");
- DwarfCUToModule::FileContext fc("dwarf-filename", &m, true);
- EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
- MockLineToModuleHandler lr;
- EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0);
-
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- // First CU. Declares class_A.
- {
- DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root1_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ProcessStrangeAttributes(&root1_handler);
- ASSERT_TRUE(root1_handler.EndAttributes());
- DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
- dwarf2reader::DW_TAG_class_type, "class_A", "");
- root1_handler.Finish();
- }
-
- // Second CU. Defines class_A, declares member_func_B.
- {
- DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root2_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ASSERT_TRUE(root2_handler.EndAttributes());
- DIEHandler *class_A_handler
- = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
- 0xb8fbfdd5f0b26fceULL);
- DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
- dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
- class_A_handler->Finish();
- delete class_A_handler;
- root2_handler.Finish();
- }
-
- // Third CU. Defines member_func_B.
- {
- DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root3_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ASSERT_TRUE(root3_handler.EndAttributes());
- DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram,
- 0xb01fef8b380bd1a2ULL, "",
- 0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL);
- root3_handler.Finish();
- }
-
- vector<Module::Function *> functions;
- m.GetFunctions(&functions, functions.end());
- EXPECT_EQ(1U, functions.size());
- EXPECT_STREQ("class_A::member_func_B", functions[0]->name.c_str());
-}
-
-TEST_F(Specifications, UnhandledInterCU) {
- Module m("module-name", "module-os", "module-arch", "module-id");
- DwarfCUToModule::FileContext fc("dwarf-filename", &m, false);
- EXPECT_CALL(reporter_, UncoveredFunction(_)).WillOnce(Return());
- MockLineToModuleHandler lr;
- EXPECT_CALL(lr, ReadProgram(_,_,_,_)).Times(0);
-
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- // First CU. Declares class_A.
- {
- DwarfCUToModule root1_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root1_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root1_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ProcessStrangeAttributes(&root1_handler);
- ASSERT_TRUE(root1_handler.EndAttributes());
- DeclarationDIE(&root1_handler, 0xb8fbfdd5f0b26fceULL,
- dwarf2reader::DW_TAG_class_type, "class_A", "");
- root1_handler.Finish();
- }
-
- // Second CU. Defines class_A, declares member_func_B.
- {
- DwarfCUToModule root2_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root2_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root2_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ASSERT_TRUE(root2_handler.EndAttributes());
- EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1);
- DIEHandler *class_A_handler
- = StartSpecifiedDIE(&root2_handler, dwarf2reader::DW_TAG_class_type,
- 0xb8fbfdd5f0b26fceULL);
- DeclarationDIE(class_A_handler, 0xb01fef8b380bd1a2ULL,
- dwarf2reader::DW_TAG_subprogram, "member_func_B", "");
- class_A_handler->Finish();
- delete class_A_handler;
- root2_handler.Finish();
- }
-
- // Third CU. Defines member_func_B.
- {
- DwarfCUToModule root3_handler(&fc, &lr, &reporter_);
- ASSERT_TRUE(root3_handler.StartCompilationUnit(0, 1, 2, 3, 3));
- ASSERT_TRUE(root3_handler.StartRootDIE(1,
- dwarf2reader::DW_TAG_compile_unit));
- ASSERT_TRUE(root3_handler.EndAttributes());
- EXPECT_CALL(reporter_, UnhandledInterCUReference(_, _)).Times(1);
- EXPECT_CALL(reporter_, UnnamedFunction(_)).Times(1);
- DefinitionDIE(&root3_handler, dwarf2reader::DW_TAG_subprogram,
- 0xb01fef8b380bd1a2ULL, "",
- 0x2618f00a1a711e53ULL, 0x4fd94b76d7c2caf5ULL);
- root3_handler.Finish();
- }
-}
-
-TEST_F(Specifications, BadOffset) {
- PushLine(0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL, "line-file", 56636272);
- EXPECT_CALL(reporter_, UnknownSpecification(_, 0x2be953efa6f9a996ULL))
- .WillOnce(Return());
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xefd7f7752c27b7e4ULL,
- dwarf2reader::DW_TAG_subprogram, "", "");
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0x2be953efa6f9a996ULL, "function",
- 0xa0277efd7ce83771ULL, 0x149554a184c730c1ULL);
- root_handler_.Finish();
-}
-
-TEST_F(Specifications, FunctionDefinitionHasOwnName) {
- PushLine(0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL, "line-file", 56792403);
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xc34ff4786cae78bdULL,
- dwarf2reader::DW_TAG_subprogram, "declaration-name", "");
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0xc34ff4786cae78bdULL, "definition-name",
- 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "definition-name",
- 0xced50b3eea81022cULL, 0x08dd4d301cc7a7d2ULL);
-}
-
-TEST_F(Specifications, ClassDefinitionHasOwnName) {
- PushLine(0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL, "line-file", 57119241);
-
- StartCU();
- DeclarationDIE(&root_handler_, 0xd0fe467ec2f1a58cULL,
- dwarf2reader::DW_TAG_class_type, "class-declaration-name", "");
-
- dwarf2reader::DIEHandler *class_definition
- = StartSpecifiedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- 0xd0fe467ec2f1a58cULL, "class-definition-name");
- ASSERT_TRUE(class_definition);
- DeclarationDIE(class_definition, 0x6d028229c15623dbULL,
- dwarf2reader::DW_TAG_subprogram,
- "function-declaration-name", "");
- class_definition->Finish();
- delete class_definition;
-
- DefinitionDIE(&root_handler_, dwarf2reader::DW_TAG_subprogram,
- 0x6d028229c15623dbULL, "function-definition-name",
- 0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL);
-
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "class-definition-name::function-definition-name",
- 0x1d0f5e0f6ce309bdULL, 0x654e1852ec3599e7ULL);
-}
-
-// DIEs that cite a specification should prefer the specification's
-// parents over their own when choosing qualified names. In this test,
-// we take the name from our definition but the enclosing scope name
-// from our declaration. I don't see why they'd ever be different, but
-// we want to verify what DwarfCUToModule is looking at.
-TEST_F(Specifications, PreferSpecificationParents) {
- PushLine(0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL, "line-file", 79488694);
-
- StartCU();
- {
- dwarf2reader::DIEHandler *declaration_class_handler =
- StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- "declaration-class");
- DeclarationDIE(declaration_class_handler, 0x9ddb35517455ef7aULL,
- dwarf2reader::DW_TAG_subprogram, "function-declaration",
- "");
- declaration_class_handler->Finish();
- delete declaration_class_handler;
- }
- {
- dwarf2reader::DIEHandler *definition_class_handler
- = StartNamedDIE(&root_handler_, dwarf2reader::DW_TAG_class_type,
- "definition-class");
- DefinitionDIE(definition_class_handler, dwarf2reader::DW_TAG_subprogram,
- 0x9ddb35517455ef7aULL, "function-definition",
- 0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL);
- definition_class_handler->Finish();
- delete definition_class_handler;
- }
- root_handler_.Finish();
-
- TestFunctionCount(1);
- TestFunction(0, "declaration-class::function-definition",
- 0xbbd9d54dce3b95b7ULL, 0x39188b7b52b0899fULL);
-}
-
-class CUErrors: public CUFixtureBase, public Test { };
-
-TEST_F(CUErrors, BadStmtList) {
- EXPECT_CALL(reporter_, BadLineInfoOffset(dummy_line_size_ + 10)).Times(1);
-
- ASSERT_TRUE(root_handler_
- .StartCompilationUnit(0xc591d5b037543d7cULL, 0x11, 0xcd,
- 0x2d7d19546cf6590cULL, 3));
- ASSERT_TRUE(root_handler_.StartRootDIE(0xae789dc102cfca54ULL,
- dwarf2reader::DW_TAG_compile_unit));
- root_handler_.ProcessAttributeString(dwarf2reader::DW_AT_name,
- dwarf2reader::DW_FORM_strp,
- "compilation-unit-name");
- root_handler_.ProcessAttributeUnsigned(dwarf2reader::DW_AT_stmt_list,
- dwarf2reader::DW_FORM_ref4,
- dummy_line_size_ + 10);
- root_handler_.EndAttributes();
- root_handler_.Finish();
-}
-
-TEST_F(CUErrors, NoLineSection) {
- EXPECT_CALL(reporter_, MissingSection(".debug_line")).Times(1);
- PushLine(0x88507fb678052611ULL, 0x42c8e9de6bbaa0faULL, "line-file", 64472290);
- // Delete the entry for .debug_line added by the fixture class's constructor.
- file_context_.ClearSectionMapForTest();
-
- StartCU();
- root_handler_.Finish();
-}
-
-TEST_F(CUErrors, BadDwarfVersion1) {
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- ASSERT_FALSE(root_handler_
- .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
- 0xc9de224ccb99ac3eULL, 1));
-}
-
-TEST_F(CUErrors, GoodDwarfVersion2) {
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- ASSERT_TRUE(root_handler_
- .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
- 0xc9de224ccb99ac3eULL, 2));
-}
-
-TEST_F(CUErrors, GoodDwarfVersion3) {
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- ASSERT_TRUE(root_handler_
- .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
- 0xc9de224ccb99ac3eULL, 3));
-}
-
-TEST_F(CUErrors, BadCURootDIETag) {
- // Kludge: satisfy reporter_'s expectation.
- reporter_.SetCUName("compilation-unit-name");
-
- ASSERT_TRUE(root_handler_
- .StartCompilationUnit(0xadf6e0eb71e2b0d9ULL, 0x4d, 0x90,
- 0xc9de224ccb99ac3eULL, 3));
-
- ASSERT_FALSE(root_handler_.StartRootDIE(0x02e56bfbda9e7337ULL,
- dwarf2reader::DW_TAG_subprogram));
-}
-
-// Tests for DwarfCUToModule::Reporter. These just produce (or fail to
-// produce) output, so their results need to be checked by hand.
-struct Reporter: public Test {
- Reporter()
- : reporter("filename", 0x123456789abcdef0ULL),
- function("function name", 0x19c45c30770c1eb0ULL),
- file("source file name") {
- reporter.SetCUName("compilation-unit-name");
-
- function.size = 0x89808a5bdfa0a6a3ULL;
- function.parameter_size = 0x6a329f18683dcd51ULL;
-
- line.address = 0x3606ac6267aebeccULL;
- line.size = 0x5de482229f32556aULL;
- line.file = &file;
- line.number = 93400201;
- }
-
- DwarfCUToModule::WarningReporter reporter;
- Module::Function function;
- Module::File file;
- Module::Line line;
-};
-
-TEST_F(Reporter, UnknownSpecification) {
- reporter.UnknownSpecification(0x123456789abcdef1ULL, 0x323456789abcdef2ULL);
-}
-
-TEST_F(Reporter, UnknownAbstractOrigin) {
- reporter.UnknownAbstractOrigin(0x123456789abcdef1ULL, 0x323456789abcdef2ULL);
-}
-
-TEST_F(Reporter, MissingSection) {
- reporter.MissingSection("section name");
-}
-
-TEST_F(Reporter, BadLineInfoOffset) {
- reporter.BadLineInfoOffset(0x123456789abcdef1ULL);
-}
-
-TEST_F(Reporter, UncoveredFunctionDisabled) {
- reporter.UncoveredFunction(function);
- EXPECT_FALSE(reporter.uncovered_warnings_enabled());
-}
-
-TEST_F(Reporter, UncoveredFunctionEnabled) {
- reporter.set_uncovered_warnings_enabled(true);
- reporter.UncoveredFunction(function);
- EXPECT_TRUE(reporter.uncovered_warnings_enabled());
-}
-
-TEST_F(Reporter, UncoveredLineDisabled) {
- reporter.UncoveredLine(line);
- EXPECT_FALSE(reporter.uncovered_warnings_enabled());
-}
-
-TEST_F(Reporter, UncoveredLineEnabled) {
- reporter.set_uncovered_warnings_enabled(true);
- reporter.UncoveredLine(line);
- EXPECT_TRUE(reporter.uncovered_warnings_enabled());
-}
-
-TEST_F(Reporter, UnnamedFunction) {
- reporter.UnnamedFunction(0x90c0baff9dedb2d9ULL);
-}
-
-// Would be nice to also test:
-// - overlapping lines, functions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.cc
deleted file mode 100644
index 258b0b603..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.cc
+++ /dev/null
@@ -1,143 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf_line_to_module.cc: Implementation of DwarfLineToModule class.
-// See dwarf_line_to_module.h for details.
-
-#include <stdio.h>
-
-#include <string>
-
-#include "common/dwarf_line_to_module.h"
-#include "common/using_std_string.h"
-
-// Trying to support Windows paths in a reasonable way adds a lot of
-// variations to test; it would be better to just put off dealing with
-// it until we actually have to deal with DWARF on Windows.
-
-// Return true if PATH is an absolute path, false if it is relative.
-static bool PathIsAbsolute(const string &path) {
- return (path.size() >= 1 && path[0] == '/');
-}
-
-static bool HasTrailingSlash(const string &path) {
- return (path.size() >= 1 && path[path.size() - 1] == '/');
-}
-
-// If PATH is an absolute path, return PATH. If PATH is a relative path,
-// treat it as relative to BASE and return the combined path.
-static string ExpandPath(const string &path,
- const string &base) {
- if (PathIsAbsolute(path) || base.empty())
- return path;
- return base + (HasTrailingSlash(base) ? "" : "/") + path;
-}
-
-namespace google_breakpad {
-
-void DwarfLineToModule::DefineDir(const string &name, uint32 dir_num) {
- // Directory number zero is reserved to mean the compilation
- // directory. Silently ignore attempts to redefine it.
- if (dir_num != 0)
- directories_[dir_num] = ExpandPath(name, compilation_dir_);
-}
-
-void DwarfLineToModule::DefineFile(const string &name, int32 file_num,
- uint32 dir_num, uint64 mod_time,
- uint64 length) {
- if (file_num == -1)
- file_num = ++highest_file_number_;
- else if (file_num > highest_file_number_)
- highest_file_number_ = file_num;
-
- string dir_name;
- if (dir_num == 0) {
- // Directory number zero is the compilation directory, and is stored as
- // an attribute on the compilation unit, rather than in the program table.
- dir_name = compilation_dir_;
- } else {
- DirectoryTable::const_iterator directory_it = directories_.find(dir_num);
- if (directory_it != directories_.end()) {
- dir_name = directory_it->second;
- } else {
- if (!warned_bad_directory_number_) {
- fprintf(stderr, "warning: DWARF line number data refers to undefined"
- " directory numbers\n");
- warned_bad_directory_number_ = true;
- }
- }
- }
-
- string full_name = ExpandPath(name, dir_name);
-
- // Find a Module::File object of the given name, and add it to the
- // file table.
- files_[file_num] = module_->FindFile(full_name);
-}
-
-void DwarfLineToModule::AddLine(uint64 address, uint64 length,
- uint32 file_num, uint32 line_num,
- uint32 column_num) {
- if (length == 0)
- return;
-
- // Clip lines not to extend beyond the end of the address space.
- if (address + length < address)
- length = -address;
-
- // Should we omit this line? (See the comments for omitted_line_end_.)
- if (address == 0 || address == omitted_line_end_) {
- omitted_line_end_ = address + length;
- return;
- } else {
- omitted_line_end_ = 0;
- }
-
- // Find the source file being referred to.
- Module::File *file = files_[file_num];
- if (!file) {
- if (!warned_bad_file_number_) {
- fprintf(stderr, "warning: DWARF line number data refers to "
- "undefined file numbers\n");
- warned_bad_file_number_ = true;
- }
- return;
- }
- Module::Line line;
- line.address = address;
- // We set the size when we get the next line or the EndSequence call.
- line.size = length;
- line.file = file;
- line.number = line_num;
- lines_->push_back(line);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.h
deleted file mode 100644
index 1fdd4cb71..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// The DwarfLineToModule class accepts line number information from a
-// DWARF parser and adds it to a google_breakpad::Module. The Module
-// can write that data out as a Breakpad symbol file.
-
-#ifndef COMMON_LINUX_DWARF_LINE_TO_MODULE_H
-#define COMMON_LINUX_DWARF_LINE_TO_MODULE_H
-
-#include <string>
-
-#include "common/module.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-// A class for producing a vector of google_breakpad::Module::Line
-// instances from parsed DWARF line number data.
-//
-// An instance of this class can be provided as a handler to a
-// dwarf2reader::LineInfo DWARF line number information parser. The
-// handler accepts source location information from the parser and
-// uses it to produce a vector of google_breakpad::Module::Line
-// objects, referring to google_breakpad::Module::File objects added
-// to a particular google_breakpad::Module.
-//
-// GNU toolchain omitted sections support:
-// ======================================
-//
-// Given the right options, the GNU toolchain will omit unreferenced
-// functions from the final executable. Unfortunately, when it does so, it
-// does not remove the associated portions of the DWARF line number
-// program; instead, it gives the DW_LNE_set_address instructions referring
-// to the now-deleted code addresses of zero. Given this input, the DWARF
-// line parser will call AddLine with a series of lines starting at address
-// zero. For example, here is the output from 'readelf -wl' for a program
-// with four functions, the first three of which have been omitted:
-//
-// Line Number Statements:
-// Extended opcode 2: set Address to 0x0
-// Advance Line by 14 to 15
-// Copy
-// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 16
-// Special opcode 119: advance Address by 8 to 0xb and Line by 2 to 18
-// Advance PC by 2 to 0xd
-// Extended opcode 1: End of Sequence
-//
-// Extended opcode 2: set Address to 0x0
-// Advance Line by 14 to 15
-// Copy
-// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 16
-// Special opcode 119: advance Address by 8 to 0xb and Line by 2 to 18
-// Advance PC by 2 to 0xd
-// Extended opcode 1: End of Sequence
-//
-// Extended opcode 2: set Address to 0x0
-// Advance Line by 19 to 20
-// Copy
-// Special opcode 48: advance Address by 3 to 0x3 and Line by 1 to 21
-// Special opcode 76: advance Address by 5 to 0x8 and Line by 1 to 22
-// Advance PC by 2 to 0xa
-// Extended opcode 1: End of Sequence
-//
-// Extended opcode 2: set Address to 0x80483a4
-// Advance Line by 23 to 24
-// Copy
-// Special opcode 202: advance Address by 14 to 0x80483b2 and Line by 1 to 25
-// Special opcode 76: advance Address by 5 to 0x80483b7 and Line by 1 to 26
-// Advance PC by 6 to 0x80483bd
-// Extended opcode 1: End of Sequence
-//
-// Instead of collecting runs of lines describing code that is not there,
-// we try to recognize and drop them. Since the linker doesn't explicitly
-// distinguish references to dropped sections from genuine references to
-// code at address zero, we must use a heuristic. We have chosen:
-//
-// - If a line starts at address zero, omit it. (On the platforms
-// breakpad targets, it is extremely unlikely that there will be code
-// at address zero.)
-//
-// - If a line starts immediately after an omitted line, omit it too.
-class DwarfLineToModule: public dwarf2reader::LineInfoHandler {
- public:
- // As the DWARF line info parser passes us line records, add source
- // files to MODULE, and add all lines to the end of LINES. LINES
- // need not be empty. If the parser hands us a zero-length line, we
- // omit it. If the parser hands us a line that extends beyond the
- // end of the address space, we clip it. It's up to our client to
- // sort out which lines belong to which functions; we don't add them
- // to any particular function in MODULE ourselves.
- DwarfLineToModule(Module *module, const string& compilation_dir,
- vector<Module::Line> *lines)
- : module_(module),
- compilation_dir_(compilation_dir),
- lines_(lines),
- highest_file_number_(-1),
- omitted_line_end_(0),
- warned_bad_file_number_(false),
- warned_bad_directory_number_(false) { }
-
- ~DwarfLineToModule() { }
-
- void DefineDir(const string &name, uint32 dir_num);
- void DefineFile(const string &name, int32 file_num,
- uint32 dir_num, uint64 mod_time,
- uint64 length);
- void AddLine(uint64 address, uint64 length,
- uint32 file_num, uint32 line_num, uint32 column_num);
-
- private:
-
- typedef std::map<uint32, string> DirectoryTable;
- typedef std::map<uint32, Module::File *> FileTable;
-
- // The module we're contributing debugging info to. Owned by our
- // client.
- Module *module_;
-
- // The compilation directory for the current compilation unit whose
- // lines are being accumulated.
- string compilation_dir_;
-
- // The vector of lines we're accumulating. Owned by our client.
- //
- // In a Module, as in a breakpad symbol file, lines belong to
- // specific functions, but DWARF simply assigns lines to addresses;
- // one must infer the line/function relationship using the
- // functions' beginning and ending addresses. So we can't add these
- // to the appropriate function from module_ until we've read the
- // function info as well. Instead, we accumulate lines here, and let
- // whoever constructed this sort it all out.
- vector<Module::Line> *lines_;
-
- // A table mapping directory numbers to paths.
- DirectoryTable directories_;
-
- // A table mapping file numbers to Module::File pointers.
- FileTable files_;
-
- // The highest file number we've seen so far, or -1 if we've seen
- // none. Used for dynamically defined file numbers.
- int32 highest_file_number_;
-
- // This is the ending address of the last line we omitted, or zero if we
- // didn't omit the previous line. It is zero before we have received any
- // AddLine calls.
- uint64 omitted_line_end_;
-
- // True if we've warned about:
- bool warned_bad_file_number_; // bad file numbers
- bool warned_bad_directory_number_; // bad directory numbers
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_DWARF_LINE_TO_MODULE_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module_unittest.cc
deleted file mode 100644
index 7c0fcfd35..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/dwarf_line_to_module_unittest.cc
+++ /dev/null
@@ -1,391 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dwarf_line_to_module.cc: Unit tests for google_breakpad::DwarfLineToModule.
-
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/dwarf_line_to_module.h"
-
-using std::vector;
-
-using google_breakpad::DwarfLineToModule;
-using google_breakpad::Module;
-using google_breakpad::Module;
-
-TEST(SimpleModule, One) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("file1", 0x30bf0f27, 0, 0, 0);
- h.AddLine(0x6fd126fbf74f2680LL, 0x63c9a14cf556712bLL, 0x30bf0f27,
- 0x4c090cbf, 0x1cf9fe0d);
-
- vector<Module::File *> files;
- m.GetFiles(&files);
- EXPECT_EQ(1U, files.size());
- EXPECT_STREQ("/file1", files[0]->name.c_str());
-
- EXPECT_EQ(1U, lines.size());
- EXPECT_EQ(0x6fd126fbf74f2680ULL, lines[0].address);
- EXPECT_EQ(0x63c9a14cf556712bULL, lines[0].size);
- EXPECT_TRUE(lines[0].file == files[0]);
- EXPECT_EQ(0x4c090cbf, lines[0].number);
-}
-
-TEST(SimpleModule, Many) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory1", 0x838299ab);
- h.DefineDir("directory2", 0xf85de023);
- h.DefineFile("file1", 0x2b80377a, 0x838299ab, 0, 0);
- h.DefineFile("file1", 0x63beb4a4, 0xf85de023, 0, 0);
- h.DefineFile("file2", 0x1d161d56, 0x838299ab, 0, 0);
- h.DefineFile("file2", 0x1e7a667c, 0xf85de023, 0, 0);
- h.AddLine(0x69900c5d553b7274ULL, 0x90fded183f0d0d3cULL, 0x2b80377a,
- 0x15b0f0a9U, 0x3ff5abd6U);
- h.AddLine(0x45811219a39b7101ULL, 0x25a5e6a924afc41fULL, 0x63beb4a4,
- 0x4d259ce9U, 0x41c5ee32U);
- h.AddLine(0xfa90514c1dc9704bULL, 0x0063efeabc02f313ULL, 0x1d161d56,
- 0x1ee9fa4fU, 0xbf70e46aU);
- h.AddLine(0x556b55fb6a647b10ULL, 0x3f3089ca2bfd80f5ULL, 0x1e7a667c,
- 0x77fc280eU, 0x2c4a728cU);
- h.DefineFile("file3", -1, 0, 0, 0);
- h.AddLine(0xe2d72a37f8d9403aULL, 0x034dfab5b0d4d236ULL, 0x63beb4a5,
- 0x75047044U, 0xb6a0016cU);
-
- vector<Module::File *> files;
- m.GetFiles(&files);
- ASSERT_EQ(5U, files.size());
- EXPECT_STREQ("/directory1/file1", files[0]->name.c_str());
- EXPECT_STREQ("/directory1/file2", files[1]->name.c_str());
- EXPECT_STREQ("/directory2/file1", files[2]->name.c_str());
- EXPECT_STREQ("/directory2/file2", files[3]->name.c_str());
- EXPECT_STREQ("/file3", files[4]->name.c_str());
-
- ASSERT_EQ(5U, lines.size());
-
- EXPECT_EQ(0x69900c5d553b7274ULL, lines[0].address);
- EXPECT_EQ(0x90fded183f0d0d3cULL, lines[0].size);
- EXPECT_TRUE(lines[0].file == files[0]);
- EXPECT_EQ(0x15b0f0a9, lines[0].number);
-
- EXPECT_EQ(0x45811219a39b7101ULL, lines[1].address);
- EXPECT_EQ(0x25a5e6a924afc41fULL, lines[1].size);
- EXPECT_TRUE(lines[1].file == files[2]);
- EXPECT_EQ(0x4d259ce9, lines[1].number);
-
- EXPECT_EQ(0xfa90514c1dc9704bULL, lines[2].address);
- EXPECT_EQ(0x0063efeabc02f313ULL, lines[2].size);
- EXPECT_TRUE(lines[2].file == files[1]);
- EXPECT_EQ(0x1ee9fa4f, lines[2].number);
-
- EXPECT_EQ(0x556b55fb6a647b10ULL, lines[3].address);
- EXPECT_EQ(0x3f3089ca2bfd80f5ULL, lines[3].size);
- EXPECT_TRUE(lines[3].file == files[3]);
- EXPECT_EQ(0x77fc280e, lines[3].number);
-
- EXPECT_EQ(0xe2d72a37f8d9403aULL, lines[4].address);
- EXPECT_EQ(0x034dfab5b0d4d236ULL, lines[4].size);
- EXPECT_TRUE(lines[4].file == files[4]);
- EXPECT_EQ(0x75047044, lines[4].number);
-}
-
-TEST(Filenames, Absolute) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory1", 1);
- h.DefineFile("/absolute", 1, 1, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- vector<Module::File *> files;
- m.GetFiles(&files);
- ASSERT_EQ(1U, files.size());
- EXPECT_STREQ("/absolute", files[0]->name.c_str());
- ASSERT_EQ(1U, lines.size());
- EXPECT_TRUE(lines[0].file == files[0]);
-}
-
-TEST(Filenames, Relative) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory1", 1);
- h.DefineFile("relative", 1, 1, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- vector<Module::File *> files;
- m.GetFiles(&files);
- ASSERT_EQ(1U, files.size());
- EXPECT_STREQ("/directory1/relative", files[0]->name.c_str());
- ASSERT_EQ(1U, lines.size());
- EXPECT_TRUE(lines[0].file == files[0]);
-}
-
-TEST(Filenames, StrangeFile) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory1", 1);
- h.DefineFile("", 1, 1, 0, 0);
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("/directory1/", lines[0].file->name.c_str());
-}
-
-TEST(Filenames, StrangeDirectory) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("", 1);
- h.DefineFile("file1", 1, 1, 0, 0);
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("/file1", lines[0].file->name.c_str());
-}
-
-TEST(Filenames, StrangeDirectoryAndFile) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("", 1);
- h.DefineFile("", 1, 1, 0, 0);
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("/", lines[0].file->name.c_str());
-}
-
-// We should use the compilation directory when encountering a file for
-// directory number zero.
-TEST(Filenames, DirectoryZeroFileIsRelativeToCompilationDir) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "src/build", &lines);
-
- h.DefineDir("Dir", 1);
- h.DefineFile("File", 1, 0, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("src/build/File", lines[0].file->name.c_str());
-}
-
-// We should treat non-absolute directories as relative to the compilation
-// directory.
-TEST(Filenames, IncludeDirectoryRelativeToDirectoryZero) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "src/build", &lines);
-
- h.DefineDir("Dir", 1);
- h.DefineFile("File", 1, 1, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("src/build/Dir/File", lines[0].file->name.c_str());
-}
-
-// We should treat absolute directories as absolute, and not relative to
-// the compilation dir.
-TEST(Filenames, IncludeDirectoryAbsolute) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "src/build", &lines);
-
- h.DefineDir("/Dir", 1);
- h.DefineFile("File", 1, 1, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("/Dir/File", lines[0].file->name.c_str());
-}
-
-// We should silently ignore attempts to define directory number zero,
-// since that is always the compilation directory.
-TEST(ModuleErrors, DirectoryZero) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory0", 0); // should be ignored
- h.DefineFile("relative", 1, 0, 0, 0);
-
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("/relative", lines[0].file->name.c_str());
-}
-
-// We should refuse to add lines with bogus file numbers. We should
-// produce only one warning, however.
-TEST(ModuleErrors, BadFileNumber) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("relative", 1, 0, 0, 0);
- h.AddLine(1, 1, 2, 0, 0); // bad file number
- h.AddLine(2, 1, 2, 0, 0); // bad file number (no duplicate warning)
-
- EXPECT_EQ(0U, lines.size());
-}
-
-// We should treat files with bogus directory numbers as relative to
-// the compilation unit.
-TEST(ModuleErrors, BadDirectoryNumber) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineDir("directory1", 1);
- h.DefineFile("baddirnumber1", 1, 2, 0, 0); // bad directory number
- h.DefineFile("baddirnumber2", 2, 2, 0, 0); // bad dir number (no warning)
- h.AddLine(1, 1, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_STREQ("baddirnumber1", lines[0].file->name.c_str());
-}
-
-// We promise not to report empty lines.
-TEST(ModuleErrors, EmptyLine) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(1, 0, 1, 0, 0);
-
- ASSERT_EQ(0U, lines.size());
-}
-
-// We are supposed to clip lines that extend beyond the end of the
-// address space.
-TEST(ModuleErrors, BigLine) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(0xffffffffffffffffULL, 2, 1, 0, 0);
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_EQ(1U, lines[0].size);
-}
-
-// The 'Omitted' tests verify that we correctly omit line information
-// for code in sections that the linker has dropped. See "GNU
-// toolchain omitted sections support" at the top of the
-// DwarfLineToModule class.
-
-TEST(Omitted, DroppedThenGood) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(0, 10, 1, 83816211, 0); // should be omitted
- h.AddLine(20, 10, 1, 13059195, 0); // should be recorded
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_EQ(13059195, lines[0].number);
-}
-
-TEST(Omitted, GoodThenDropped) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(0x9dd6a372, 10, 1, 41454594, 0); // should be recorded
- h.AddLine(0, 10, 1, 44793413, 0); // should be omitted
-
- ASSERT_EQ(1U, lines.size());
- EXPECT_EQ(41454594, lines[0].number);
-}
-
-TEST(Omitted, Mix1) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(0x679ed72f, 10, 1, 58932642, 0); // should be recorded
- h.AddLine(0xdfb5a72d, 10, 1, 39847385, 0); // should be recorded
- h.AddLine(0, 0x78, 1, 23053829, 0); // should be omitted
- h.AddLine(0x78, 0x6a, 1, 65317783, 0); // should be omitted
- h.AddLine(0x78 + 0x6a, 0x2a, 1, 77601423, 0); // should be omitted
- h.AddLine(0x9fe0cea5, 10, 1, 91806582, 0); // should be recorded
- h.AddLine(0x7e41a109, 10, 1, 56169221, 0); // should be recorded
-
- ASSERT_EQ(4U, lines.size());
- EXPECT_EQ(58932642, lines[0].number);
- EXPECT_EQ(39847385, lines[1].number);
- EXPECT_EQ(91806582, lines[2].number);
- EXPECT_EQ(56169221, lines[3].number);
-}
-
-TEST(Omitted, Mix2) {
- Module m("name", "os", "architecture", "id");
- vector<Module::Line> lines;
- DwarfLineToModule h(&m, "/", &lines);
-
- h.DefineFile("filename1", 1, 0, 0, 0);
- h.AddLine(0, 0xf2, 1, 58802211, 0); // should be omitted
- h.AddLine(0xf2, 0xb9, 1, 78958222, 0); // should be omitted
- h.AddLine(0xf2 + 0xb9, 0xf7, 1, 64861892, 0); // should be omitted
- h.AddLine(0x4e4d271e, 9, 1, 67355743, 0); // should be recorded
- h.AddLine(0xdfb5a72d, 30, 1, 23365776, 0); // should be recorded
- h.AddLine(0, 0x64, 1, 76196762, 0); // should be omitted
- h.AddLine(0x64, 0x33, 1, 71066611, 0); // should be omitted
- h.AddLine(0x64 + 0x33, 0xe3, 1, 61749337, 0); // should be omitted
-
- ASSERT_EQ(2U, lines.size());
- EXPECT_EQ(67355743, lines[0].number);
- EXPECT_EQ(23365776, lines[1].number);
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/language.cc b/toolkit/crashreporter/google-breakpad/src/common/language.cc
deleted file mode 100644
index c2fd81f64..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/language.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// language.cc: Subclasses and singletons for google_breakpad::Language.
-// See language.h for details.
-
-#include "common/language.h"
-
-namespace google_breakpad {
-
-// C++ language-specific operations.
-class CPPLanguage: public Language {
- public:
- CPPLanguage() {}
- string MakeQualifiedName(const string &parent_name,
- const string &name) const {
- if (parent_name.empty())
- return name;
- else
- return parent_name + "::" + name;
- }
-};
-
-CPPLanguage CPPLanguageSingleton;
-
-// Java language-specific operations.
-class JavaLanguage: public Language {
- public:
- string MakeQualifiedName(const string &parent_name,
- const string &name) const {
- if (parent_name.empty())
- return name;
- else
- return parent_name + "." + name;
- }
-};
-
-JavaLanguage JavaLanguageSingleton;
-
-// Assembler language-specific operations.
-class AssemblerLanguage: public Language {
- bool HasFunctions() const { return false; }
- string MakeQualifiedName(const string &parent_name,
- const string &name) const {
- return name;
- }
-};
-
-AssemblerLanguage AssemblerLanguageSingleton;
-
-const Language * const Language::CPlusPlus = &CPPLanguageSingleton;
-const Language * const Language::Java = &JavaLanguageSingleton;
-const Language * const Language::Assembler = &AssemblerLanguageSingleton;
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/language.h b/toolkit/crashreporter/google-breakpad/src/common/language.h
deleted file mode 100644
index bbe303347..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/language.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// language.h: Define google_breakpad::Language. Instances of
-// subclasses of this class provide language-appropriate operations
-// for the Breakpad symbol dumper.
-
-#ifndef COMMON_LINUX_LANGUAGE_H__
-#define COMMON_LINUX_LANGUAGE_H__
-
-#include <string>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-// An abstract base class for language-specific operations. We choose
-// an instance of a subclass of this when we find the CU's language.
-// This class's definitions are appropriate for CUs with no specified
-// language.
-class Language {
- public:
- // A base class destructor should be either public and virtual,
- // or protected and nonvirtual.
- virtual ~Language() {}
-
- // Return true if this language has functions to which we can assign
- // line numbers. (Debugging info for assembly language, for example,
- // can have source location information, but does not have functions
- // recorded using DW_TAG_subprogram DIEs.)
- virtual bool HasFunctions() const { return true; }
-
- // Construct a fully-qualified, language-appropriate form of NAME,
- // given that PARENT_NAME is the name of the construct enclosing
- // NAME. If PARENT_NAME is the empty string, then NAME is a
- // top-level name.
- //
- // This API sort of assumes that a fully-qualified name is always
- // some simple textual composition of the unqualified name and its
- // parent's name, and that we don't need to know anything else about
- // the parent or the child (say, their DIEs' tags) to do the job.
- // This is true for the languages we support at the moment, and
- // keeps things concrete. Perhaps a more refined operation would
- // take into account the parent and child DIE types, allow languages
- // to use their own data type for complex parent names, etc. But if
- // C++ doesn't need all that, who would?
- virtual string MakeQualifiedName (const string &parent_name,
- const string &name) const = 0;
-
- // Instances for specific languages.
- static const Language * const CPlusPlus,
- * const Java,
- * const Assembler;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_LANGUAGE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc
deleted file mode 100644
index 8df636ce4..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/linux/crc32.h"
-
-namespace google_breakpad {
-
-// This implementation is based on the sample implementation in RFC 1952.
-
-// CRC32 polynomial, in reversed form.
-// See RFC 1952, or http://en.wikipedia.org/wiki/Cyclic_redundancy_check
-static const uint32_t kCrc32Polynomial = 0xEDB88320;
-static uint32_t kCrc32Table[256] = { 0 };
-
-#define arraysize(f) (sizeof(f) / sizeof(*f))
-
-static void EnsureCrc32TableInited() {
- if (kCrc32Table[arraysize(kCrc32Table) - 1])
- return; // already inited
- for (uint32_t i = 0; i < arraysize(kCrc32Table); ++i) {
- uint32_t c = i;
- for (size_t j = 0; j < 8; ++j) {
- if (c & 1) {
- c = kCrc32Polynomial ^ (c >> 1);
- } else {
- c >>= 1;
- }
- }
- kCrc32Table[i] = c;
- }
-}
-
-uint32_t UpdateCrc32(uint32_t start, const void* buf, size_t len) {
- EnsureCrc32TableInited();
-
- uint32_t c = start ^ 0xFFFFFFFF;
- const uint8_t* u = static_cast<const uint8_t*>(buf);
- for (size_t i = 0; i < len; ++i) {
- c = kCrc32Table[(c ^ u[i]) & 0xFF] ^ (c >> 8);
- }
- return c ^ 0xFFFFFFFF;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h b/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h
deleted file mode 100644
index e3d9db92b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/crc32.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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 COMMON_LINUX_CRC32_H_
-#define COMMON_LINUX_CRC32_H_
-
-#include <stdint.h>
-
-#include <string>
-
-namespace google_breakpad {
-
-// Updates a CRC32 checksum with |len| bytes from |buf|. |initial| holds the
-// checksum result from the previous update; for the first call, it should be 0.
-uint32_t UpdateCrc32(uint32_t initial, const void* buf, size_t len);
-
-// Computes a CRC32 checksum using |len| bytes from |buf|.
-inline uint32_t ComputeCrc32(const void* buf, size_t len) {
- return UpdateCrc32(0, buf, len);
-}
-inline uint32_t ComputeCrc32(const std::string& str) {
- return ComputeCrc32(str.c_str(), str.size());
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_CRC32_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
deleted file mode 100644
index cd99bee66..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.cc
+++ /dev/null
@@ -1,1159 +0,0 @@
-// 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.
-
-// Restructured in 2009 by: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_symbols.cc: implement google_breakpad::WriteSymbolFile:
-// Find all the debugging info in a file and dump it as a Breakpad symbol file.
-
-#include "common/linux/dump_symbols.h"
-
-#include <assert.h>
-#include <elf.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <link.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <iostream>
-#include <set>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "common/arm_ex_reader.h"
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/dwarf2diehandler.h"
-#include "common/dwarf_cfi_to_module.h"
-#include "common/dwarf_cu_to_module.h"
-#include "common/dwarf_line_to_module.h"
-#include "common/linux/crc32.h"
-#include "common/linux/eintr_wrapper.h"
-#include "common/linux/elfutils.h"
-#include "common/linux/elfutils-inl.h"
-#include "common/linux/elf_symbols_to_module.h"
-#include "common/linux/file_id.h"
-#include "common/memory.h"
-#include "common/module.h"
-#include "common/scoped_ptr.h"
-#ifndef NO_STABS_SUPPORT
-#include "common/stabs_reader.h"
-#include "common/stabs_to_module.h"
-#endif
-#include "common/using_std_string.h"
-
-#ifndef SHT_ARM_EXIDX
-// bionic and older glibc don't define this
-# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
-#endif
-
-// This namespace contains helper functions.
-namespace {
-
-using google_breakpad::DumpOptions;
-using google_breakpad::DwarfCFIToModule;
-using google_breakpad::DwarfCUToModule;
-using google_breakpad::DwarfLineToModule;
-using google_breakpad::ElfClass;
-using google_breakpad::ElfClass32;
-using google_breakpad::ElfClass64;
-using google_breakpad::FileID;
-using google_breakpad::FindElfSectionByName;
-using google_breakpad::GetOffset;
-using google_breakpad::IsValidElf;
-using google_breakpad::kDefaultBuildIdSize;
-using google_breakpad::Module;
-using google_breakpad::PageAllocator;
-#ifndef NO_STABS_SUPPORT
-using google_breakpad::StabsToModule;
-#endif
-using google_breakpad::scoped_ptr;
-using google_breakpad::wasteful_vector;
-
-// Define AARCH64 ELF architecture if host machine does not include this define.
-#ifndef EM_AARCH64
-#define EM_AARCH64 183
-#endif
-
-// Define SHT_ANDROID_REL and SHT_ANDROID_RELA if not defined by the host.
-// Sections with this type contain Android packed relocations.
-#ifndef SHT_ANDROID_REL
-#define SHT_ANDROID_REL (SHT_LOOS + 1)
-#endif
-#ifndef SHT_ANDROID_RELA
-#define SHT_ANDROID_RELA (SHT_LOOS + 2)
-#endif
-
-//
-// FDWrapper
-//
-// Wrapper class to make sure opened file is closed.
-//
-class FDWrapper {
- public:
- explicit FDWrapper(int fd) :
- fd_(fd) {}
- ~FDWrapper() {
- if (fd_ != -1)
- close(fd_);
- }
- int get() {
- return fd_;
- }
- int release() {
- int fd = fd_;
- fd_ = -1;
- return fd;
- }
- private:
- int fd_;
-};
-
-//
-// MmapWrapper
-//
-// Wrapper class to make sure mapped regions are unmapped.
-//
-class MmapWrapper {
- public:
- MmapWrapper() : is_set_(false) {}
- ~MmapWrapper() {
- if (is_set_ && base_ != NULL) {
- assert(size_ > 0);
- munmap(base_, size_);
- }
- }
- void set(void *mapped_address, size_t mapped_size) {
- is_set_ = true;
- base_ = mapped_address;
- size_ = mapped_size;
- }
- void release() {
- assert(is_set_);
- is_set_ = false;
- base_ = NULL;
- size_ = 0;
- }
-
- private:
- bool is_set_;
- void* base_;
- size_t size_;
-};
-
-// Find the preferred loading address of the binary.
-template<typename ElfClass>
-typename ElfClass::Addr GetLoadingAddress(
- const typename ElfClass::Phdr* program_headers,
- int nheader) {
- typedef typename ElfClass::Phdr Phdr;
-
- // For non-PIC executables (e_type == ET_EXEC), the load address is
- // the start address of the first PT_LOAD segment. (ELF requires
- // the segments to be sorted by load address.) For PIC executables
- // and dynamic libraries (e_type == ET_DYN), this address will
- // normally be zero.
- for (int i = 0; i < nheader; ++i) {
- const Phdr& header = program_headers[i];
- if (header.p_type == PT_LOAD)
- return header.p_vaddr;
- }
- return 0;
-}
-
-#ifndef NO_STABS_SUPPORT
-template<typename ElfClass>
-bool LoadStabs(const typename ElfClass::Ehdr* elf_header,
- const typename ElfClass::Shdr* stab_section,
- const typename ElfClass::Shdr* stabstr_section,
- const bool big_endian,
- Module* module) {
- // A callback object to handle data from the STABS reader.
- StabsToModule handler(module);
- // Find the addresses of the STABS data, and create a STABS reader object.
- // On Linux, STABS entries always have 32-bit values, regardless of the
- // address size of the architecture whose code they're describing, and
- // the strings are always "unitized".
- const uint8_t* stabs =
- GetOffset<ElfClass, uint8_t>(elf_header, stab_section->sh_offset);
- const uint8_t* stabstr =
- GetOffset<ElfClass, uint8_t>(elf_header, stabstr_section->sh_offset);
- google_breakpad::StabsReader reader(stabs, stab_section->sh_size,
- stabstr, stabstr_section->sh_size,
- big_endian, 4, true, &handler);
- // Read the STABS data, and do post-processing.
- if (!reader.Process())
- return false;
- handler.Finalize();
- return true;
-}
-#endif // NO_STABS_SUPPORT
-
-// A line-to-module loader that accepts line number info parsed by
-// dwarf2reader::LineInfo and populates a Module and a line vector
-// with the results.
-class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler {
- public:
- // Create a line-to-module converter using BYTE_READER.
- explicit DumperLineToModule(dwarf2reader::ByteReader *byte_reader)
- : byte_reader_(byte_reader) { }
- void StartCompilationUnit(const string& compilation_dir) {
- compilation_dir_ = compilation_dir;
- }
- void ReadProgram(const uint8_t *program, uint64 length,
- Module* module, std::vector<Module::Line>* lines) {
- DwarfLineToModule handler(module, compilation_dir_, lines);
- dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler);
- parser.Start();
- }
- private:
- string compilation_dir_;
- dwarf2reader::ByteReader *byte_reader_;
-};
-
-template<typename ElfClass>
-bool LoadDwarf(const string& dwarf_filename,
- const typename ElfClass::Ehdr* elf_header,
- const bool big_endian,
- bool handle_inter_cu_refs,
- Module* module) {
- typedef typename ElfClass::Shdr Shdr;
-
- const dwarf2reader::Endianness endianness = big_endian ?
- dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
- dwarf2reader::ByteReader byte_reader(endianness);
-
- // Construct a context for this file.
- DwarfCUToModule::FileContext file_context(dwarf_filename,
- module,
- handle_inter_cu_refs);
-
- // Build a map of the ELF file's sections.
- const Shdr* sections =
- GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
- int num_sections = elf_header->e_shnum;
- const Shdr* section_names = sections + elf_header->e_shstrndx;
- for (int i = 0; i < num_sections; i++) {
- const Shdr* section = &sections[i];
- string name = GetOffset<ElfClass, char>(elf_header,
- section_names->sh_offset) +
- section->sh_name;
- const uint8_t *contents = GetOffset<ElfClass, uint8_t>(elf_header,
- section->sh_offset);
- file_context.AddSectionToSectionMap(name, contents, section->sh_size);
- }
-
- // Parse all the compilation units in the .debug_info section.
- DumperLineToModule line_to_module(&byte_reader);
- dwarf2reader::SectionMap::const_iterator debug_info_entry =
- file_context.section_map().find(".debug_info");
- assert(debug_info_entry != file_context.section_map().end());
- const std::pair<const uint8_t *, uint64>& debug_info_section =
- debug_info_entry->second;
- // This should never have been called if the file doesn't have a
- // .debug_info section.
- assert(debug_info_section.first);
- uint64 debug_info_length = debug_info_section.second;
- for (uint64 offset = 0; offset < debug_info_length;) {
- // Make a handler for the root DIE that populates MODULE with the
- // data that was found.
- DwarfCUToModule::WarningReporter reporter(dwarf_filename, offset);
- DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter);
- // Make a Dwarf2Handler that drives the DIEHandler.
- dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
- // Make a DWARF parser for the compilation unit at OFFSET.
- dwarf2reader::CompilationUnit reader(dwarf_filename,
- file_context.section_map(),
- offset,
- &byte_reader,
- &die_dispatcher);
- // Process the entire compilation unit; get the offset of the next.
- offset += reader.Start();
- }
- return true;
-}
-
-// Fill REGISTER_NAMES with the register names appropriate to the
-// machine architecture given in HEADER, indexed by the register
-// numbers used in DWARF call frame information. Return true on
-// success, or false if HEADER's machine architecture is not
-// supported.
-template<typename ElfClass>
-bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
- std::vector<string>* register_names) {
- switch (elf_header->e_machine) {
- case EM_386:
- *register_names = DwarfCFIToModule::RegisterNames::I386();
- return true;
- case EM_ARM:
- *register_names = DwarfCFIToModule::RegisterNames::ARM();
- return true;
- case EM_AARCH64:
- *register_names = DwarfCFIToModule::RegisterNames::ARM64();
- return true;
- case EM_MIPS:
- *register_names = DwarfCFIToModule::RegisterNames::MIPS();
- return true;
- case EM_X86_64:
- *register_names = DwarfCFIToModule::RegisterNames::X86_64();
- return true;
- default:
- return false;
- }
-}
-
-template<typename ElfClass>
-bool LoadDwarfCFI(const string& dwarf_filename,
- const typename ElfClass::Ehdr* elf_header,
- const char* section_name,
- const typename ElfClass::Shdr* section,
- const bool eh_frame,
- const typename ElfClass::Shdr* got_section,
- const typename ElfClass::Shdr* text_section,
- const bool big_endian,
- Module* module) {
- // Find the appropriate set of register names for this file's
- // architecture.
- std::vector<string> register_names;
- if (!DwarfCFIRegisterNames<ElfClass>(elf_header, &register_names)) {
- fprintf(stderr, "%s: unrecognized ELF machine architecture '%d';"
- " cannot convert DWARF call frame information\n",
- dwarf_filename.c_str(), elf_header->e_machine);
- return false;
- }
-
- const dwarf2reader::Endianness endianness = big_endian ?
- dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
-
- // Find the call frame information and its size.
- const uint8_t *cfi =
- GetOffset<ElfClass, uint8_t>(elf_header, section->sh_offset);
- size_t cfi_size = section->sh_size;
-
- // Plug together the parser, handler, and their entourages.
- DwarfCFIToModule::Reporter module_reporter(dwarf_filename, section_name);
- DwarfCFIToModule handler(module, register_names, &module_reporter);
- dwarf2reader::ByteReader byte_reader(endianness);
-
- byte_reader.SetAddressSize(ElfClass::kAddrSize);
-
- // Provide the base addresses for .eh_frame encoded pointers, if
- // possible.
- byte_reader.SetCFIDataBase(section->sh_addr, cfi);
- if (got_section)
- byte_reader.SetDataBase(got_section->sh_addr);
- if (text_section)
- byte_reader.SetTextBase(text_section->sh_addr);
-
- dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(dwarf_filename,
- section_name);
- dwarf2reader::CallFrameInfo parser(cfi, cfi_size,
- &byte_reader, &handler, &dwarf_reporter,
- eh_frame);
- parser.Start();
- return true;
-}
-
-template<typename ElfClass>
-bool LoadARMexidx(const typename ElfClass::Ehdr* elf_header,
- const typename ElfClass::Shdr* exidx_section,
- const typename ElfClass::Shdr* extab_section,
- uint32_t loading_addr,
- Module* module) {
- // To do this properly we need to know:
- // * the bounds of the .ARM.exidx section in the mapped image
- // * the bounds of the .ARM.extab section in the mapped image
- // * the vma of the last byte in the text section associated with the .exidx
- // The first two are easy. The third is a bit tricky. If we can't
- // figure out what it is, just pass in zero.
- const char *exidx_img
- = GetOffset<ElfClass, char>(elf_header, exidx_section->sh_offset);
- size_t exidx_size = exidx_section->sh_size;
- const char *extab_img
- = GetOffset<ElfClass, char>(elf_header, extab_section->sh_offset);
- size_t extab_size = extab_section->sh_size;
-
- // The sh_link field of the exidx section gives the section number
- // for the associated text section.
- uint32_t exidx_text_last_svma = 0;
- int exidx_text_sno = exidx_section->sh_link;
- typedef typename ElfClass::Shdr Shdr;
- // |sections| points to the section header table
- const Shdr* sections
- = GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
- const int num_sections = elf_header->e_shnum;
- if (exidx_text_sno >= 0 && exidx_text_sno < num_sections) {
- const Shdr* exidx_text_shdr = &sections[exidx_text_sno];
- if (exidx_text_shdr->sh_size > 0) {
- exidx_text_last_svma
- = exidx_text_shdr->sh_addr + exidx_text_shdr->sh_size - 1;
- }
- }
-
- arm_ex_to_module::ARMExToModule handler(module);
- arm_ex_reader::ExceptionTableInfo
- parser(exidx_img, exidx_size, extab_img, extab_size, exidx_text_last_svma,
- &handler,
- reinterpret_cast<const char*>(elf_header),
- loading_addr);
- parser.Start();
- return true;
-}
-
-bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper,
- void** elf_header) {
- int obj_fd = open(obj_file.c_str(), O_RDONLY);
- if (obj_fd < 0) {
- fprintf(stderr, "Failed to open ELF file '%s': %s\n",
- obj_file.c_str(), strerror(errno));
- return false;
- }
- FDWrapper obj_fd_wrapper(obj_fd);
- struct stat st;
- if (fstat(obj_fd, &st) != 0 && st.st_size <= 0) {
- fprintf(stderr, "Unable to fstat ELF file '%s': %s\n",
- obj_file.c_str(), strerror(errno));
- return false;
- }
- void* obj_base = mmap(NULL, st.st_size,
- PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0);
- if (obj_base == MAP_FAILED) {
- fprintf(stderr, "Failed to mmap ELF file '%s': %s\n",
- obj_file.c_str(), strerror(errno));
- return false;
- }
- map_wrapper->set(obj_base, st.st_size);
- *elf_header = obj_base;
- if (!IsValidElf(*elf_header)) {
- fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
- return false;
- }
- return true;
-}
-
-// Get the endianness of ELF_HEADER. If it's invalid, return false.
-template<typename ElfClass>
-bool ElfEndianness(const typename ElfClass::Ehdr* elf_header,
- bool* big_endian) {
- if (elf_header->e_ident[EI_DATA] == ELFDATA2LSB) {
- *big_endian = false;
- return true;
- }
- if (elf_header->e_ident[EI_DATA] == ELFDATA2MSB) {
- *big_endian = true;
- return true;
- }
-
- fprintf(stderr, "bad data encoding in ELF header: %d\n",
- elf_header->e_ident[EI_DATA]);
- return false;
-}
-
-// Given |left_abspath|, find the absolute path for |right_path| and see if the
-// two absolute paths are the same.
-bool IsSameFile(const char* left_abspath, const string& right_path) {
- char right_abspath[PATH_MAX];
- if (!realpath(right_path.c_str(), right_abspath))
- return false;
- return strcmp(left_abspath, right_abspath) == 0;
-}
-
-// Read the .gnu_debuglink and get the debug file name. If anything goes
-// wrong, return an empty string.
-string ReadDebugLink(const uint8_t *debuglink,
- const size_t debuglink_size,
- const bool big_endian,
- const string& obj_file,
- const std::vector<string>& debug_dirs) {
- // Include '\0' + CRC32 (4 bytes).
- size_t debuglink_len = strlen(reinterpret_cast<const char *>(debuglink)) + 5;
- debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes.
-
- // Sanity check.
- if (debuglink_len != debuglink_size) {
- fprintf(stderr, "Mismatched .gnu_debuglink string / section size: "
- "%zx %zx\n", debuglink_len, debuglink_size);
- return string();
- }
-
- char obj_file_abspath[PATH_MAX];
- if (!realpath(obj_file.c_str(), obj_file_abspath)) {
- fprintf(stderr, "Cannot resolve absolute path for %s\n", obj_file.c_str());
- return string();
- }
-
- std::vector<string> searched_paths;
- string debuglink_path;
- std::vector<string>::const_iterator it;
- for (it = debug_dirs.begin(); it < debug_dirs.end(); ++it) {
- const string& debug_dir = *it;
- debuglink_path = debug_dir + "/" +
- reinterpret_cast<const char *>(debuglink);
-
- // There is the annoying case of /path/to/foo.so having foo.so as the
- // debug link file name. Thus this may end up opening /path/to/foo.so again,
- // and there is a small chance of the two files having the same CRC.
- if (IsSameFile(obj_file_abspath, debuglink_path))
- continue;
-
- searched_paths.push_back(debug_dir);
- int debuglink_fd = open(debuglink_path.c_str(), O_RDONLY);
- if (debuglink_fd < 0)
- continue;
-
- FDWrapper debuglink_fd_wrapper(debuglink_fd);
-
- // The CRC is the last 4 bytes in |debuglink|.
- const dwarf2reader::Endianness endianness = big_endian ?
- dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE;
- dwarf2reader::ByteReader byte_reader(endianness);
- uint32_t expected_crc =
- byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]);
-
- uint32_t actual_crc = 0;
- while (true) {
- const size_t kReadSize = 4096;
- char buf[kReadSize];
- ssize_t bytes_read = HANDLE_EINTR(read(debuglink_fd, &buf, kReadSize));
- if (bytes_read < 0) {
- fprintf(stderr, "Error reading debug ELF file %s.\n",
- debuglink_path.c_str());
- return string();
- }
- if (bytes_read == 0)
- break;
- actual_crc = google_breakpad::UpdateCrc32(actual_crc, buf, bytes_read);
- }
- if (actual_crc != expected_crc) {
- fprintf(stderr, "Error reading debug ELF file - CRC32 mismatch: %s\n",
- debuglink_path.c_str());
- continue;
- }
-
- // Found debug file.
- return debuglink_path;
- }
-
- // Not found case.
- fprintf(stderr, "Failed to find debug ELF file for '%s' after trying:\n",
- obj_file.c_str());
- for (it = searched_paths.begin(); it < searched_paths.end(); ++it) {
- const string& debug_dir = *it;
- fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink);
- }
- return string();
-}
-
-//
-// LoadSymbolsInfo
-//
-// Holds the state between the two calls to LoadSymbols() in case it's necessary
-// to follow the .gnu_debuglink section and load debug information from a
-// different file.
-//
-template<typename ElfClass>
-class LoadSymbolsInfo {
- public:
- typedef typename ElfClass::Addr Addr;
-
- explicit LoadSymbolsInfo(const std::vector<string>& dbg_dirs) :
- debug_dirs_(dbg_dirs),
- has_loading_addr_(false) {}
-
- // Keeps track of which sections have been loaded so sections don't
- // accidentally get loaded twice from two different files.
- void LoadedSection(const string &section) {
- if (loaded_sections_.count(section) == 0) {
- loaded_sections_.insert(section);
- } else {
- fprintf(stderr, "Section %s has already been loaded.\n",
- section.c_str());
- }
- }
-
- // The ELF file and linked debug file are expected to have the same preferred
- // loading address.
- void set_loading_addr(Addr addr, const string &filename) {
- if (!has_loading_addr_) {
- loading_addr_ = addr;
- loaded_file_ = filename;
- return;
- }
-
- if (addr != loading_addr_) {
- fprintf(stderr,
- "ELF file '%s' and debug ELF file '%s' "
- "have different load addresses.\n",
- loaded_file_.c_str(), filename.c_str());
- assert(false);
- }
- }
-
- // Setters and getters
- const std::vector<string>& debug_dirs() const {
- return debug_dirs_;
- }
-
- string debuglink_file() const {
- return debuglink_file_;
- }
- void set_debuglink_file(string file) {
- debuglink_file_ = file;
- }
-
- private:
- const std::vector<string>& debug_dirs_; // Directories in which to
- // search for the debug ELF file.
-
- string debuglink_file_; // Full path to the debug ELF file.
-
- bool has_loading_addr_; // Indicate if LOADING_ADDR_ is valid.
-
- Addr loading_addr_; // Saves the preferred loading address from the
- // first call to LoadSymbols().
-
- string loaded_file_; // Name of the file loaded from the first call to
- // LoadSymbols().
-
- std::set<string> loaded_sections_; // Tracks the Loaded ELF sections
- // between calls to LoadSymbols().
-};
-
-template<typename ElfClass>
-bool LoadSymbols(const string& obj_file,
- const bool big_endian,
- const typename ElfClass::Ehdr* elf_header,
- const bool read_gnu_debug_link,
- LoadSymbolsInfo<ElfClass>* info,
- const DumpOptions& options,
- Module* module) {
- typedef typename ElfClass::Addr Addr;
- typedef typename ElfClass::Phdr Phdr;
- typedef typename ElfClass::Shdr Shdr;
- typedef typename ElfClass::Word Word;
-
- Addr loading_addr = GetLoadingAddress<ElfClass>(
- GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff),
- elf_header->e_phnum);
- module->SetLoadAddress(loading_addr);
- info->set_loading_addr(loading_addr, obj_file);
-
- Word debug_section_type =
- elf_header->e_machine == EM_MIPS ? SHT_MIPS_DWARF : SHT_PROGBITS;
- const Shdr* sections =
- GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
- const Shdr* section_names = sections + elf_header->e_shstrndx;
- const char* names =
- GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
- const char *names_end = names + section_names->sh_size;
- bool found_debug_info_section = false;
- bool found_usable_info = false;
-
- // Reject files that contain Android packed relocations. The pre-packed
- // version of the file should be symbolized; the packed version is only
- // intended for use on the target system.
- if (FindElfSectionByName<ElfClass>(".rel.dyn", SHT_ANDROID_REL,
- sections, names,
- names_end, elf_header->e_shnum)) {
- fprintf(stderr, "%s: file contains a \".rel.dyn\" section "
- "with type SHT_ANDROID_REL\n", obj_file.c_str());
- fprintf(stderr, "Files containing Android packed relocations "
- "may not be symbolized.\n");
- return false;
- }
- if (FindElfSectionByName<ElfClass>(".rela.dyn", SHT_ANDROID_RELA,
- sections, names,
- names_end, elf_header->e_shnum)) {
- fprintf(stderr, "%s: file contains a \".rela.dyn\" section "
- "with type SHT_ANDROID_RELA\n", obj_file.c_str());
- fprintf(stderr, "Files containing Android packed relocations "
- "may not be symbolized.\n");
- return false;
- }
-
- if (options.symbol_data != ONLY_CFI) {
-#ifndef NO_STABS_SUPPORT
- // Look for STABS debugging information, and load it if present.
- const Shdr* stab_section =
- FindElfSectionByName<ElfClass>(".stab", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- if (stab_section) {
- const Shdr* stabstr_section = stab_section->sh_link + sections;
- if (stabstr_section) {
- found_debug_info_section = true;
- found_usable_info = true;
- info->LoadedSection(".stab");
- if (!LoadStabs<ElfClass>(elf_header, stab_section, stabstr_section,
- big_endian, module)) {
- fprintf(stderr, "%s: \".stab\" section found, but failed to load"
- " STABS debugging information\n", obj_file.c_str());
- }
- }
- }
-#endif // NO_STABS_SUPPORT
-
- // Look for DWARF debugging information, and load it if present.
- const Shdr* dwarf_section =
- FindElfSectionByName<ElfClass>(".debug_info", debug_section_type,
- sections, names, names_end,
- elf_header->e_shnum);
- if (dwarf_section) {
- found_debug_info_section = true;
- found_usable_info = true;
- info->LoadedSection(".debug_info");
- if (!LoadDwarf<ElfClass>(obj_file, elf_header, big_endian,
- options.handle_inter_cu_refs, module)) {
- fprintf(stderr, "%s: \".debug_info\" section found, but failed to load "
- "DWARF debugging information\n", obj_file.c_str());
- }
- }
-
- // See if there are export symbols available.
- const Shdr* symtab_section =
- FindElfSectionByName<ElfClass>(".symtab", SHT_SYMTAB,
- sections, names, names_end,
- elf_header->e_shnum);
- const Shdr* strtab_section =
- FindElfSectionByName<ElfClass>(".strtab", SHT_STRTAB,
- sections, names, names_end,
- elf_header->e_shnum);
- if (symtab_section && strtab_section) {
- info->LoadedSection(".symtab");
-
- const uint8_t* symtab =
- GetOffset<ElfClass, uint8_t>(elf_header,
- symtab_section->sh_offset);
- const uint8_t* strtab =
- GetOffset<ElfClass, uint8_t>(elf_header,
- strtab_section->sh_offset);
- bool result =
- ELFSymbolsToModule(symtab,
- symtab_section->sh_size,
- strtab,
- strtab_section->sh_size,
- big_endian,
- ElfClass::kAddrSize,
- module);
- found_usable_info = found_usable_info || result;
- } else {
- // Look in dynsym only if full symbol table was not available.
- const Shdr* dynsym_section =
- FindElfSectionByName<ElfClass>(".dynsym", SHT_DYNSYM,
- sections, names, names_end,
- elf_header->e_shnum);
- const Shdr* dynstr_section =
- FindElfSectionByName<ElfClass>(".dynstr", SHT_STRTAB,
- sections, names, names_end,
- elf_header->e_shnum);
- if (dynsym_section && dynstr_section) {
- info->LoadedSection(".dynsym");
-
- const uint8_t* dynsyms =
- GetOffset<ElfClass, uint8_t>(elf_header,
- dynsym_section->sh_offset);
- const uint8_t* dynstrs =
- GetOffset<ElfClass, uint8_t>(elf_header,
- dynstr_section->sh_offset);
- bool result =
- ELFSymbolsToModule(dynsyms,
- dynsym_section->sh_size,
- dynstrs,
- dynstr_section->sh_size,
- big_endian,
- ElfClass::kAddrSize,
- module);
- found_usable_info = found_usable_info || result;
- }
- }
- }
-
- if (options.symbol_data != NO_CFI) {
- // Dwarf Call Frame Information (CFI) is actually independent from
- // the other DWARF debugging information, and can be used alone.
- const Shdr* dwarf_cfi_section =
- FindElfSectionByName<ElfClass>(".debug_frame", debug_section_type,
- sections, names, names_end,
- elf_header->e_shnum);
- if (dwarf_cfi_section) {
- // Ignore the return value of this function; even without call frame
- // information, the other debugging information could be perfectly
- // useful.
- info->LoadedSection(".debug_frame");
- bool result =
- LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".debug_frame",
- dwarf_cfi_section, false, 0, 0, big_endian,
- module);
- found_usable_info = found_usable_info || result;
- }
-
- // Linux C++ exception handling information can also provide
- // unwinding data.
- const Shdr* eh_frame_section =
- FindElfSectionByName<ElfClass>(".eh_frame", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- if (eh_frame_section) {
- // Pointers in .eh_frame data may be relative to the base addresses of
- // certain sections. Provide those sections if present.
- const Shdr* got_section =
- FindElfSectionByName<ElfClass>(".got", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- const Shdr* text_section =
- FindElfSectionByName<ElfClass>(".text", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- info->LoadedSection(".eh_frame");
- // As above, ignore the return value of this function.
- bool result =
- LoadDwarfCFI<ElfClass>(obj_file, elf_header, ".eh_frame",
- eh_frame_section, true,
- got_section, text_section, big_endian, module);
- found_usable_info = found_usable_info || result;
- }
- }
-
- // ARM has special unwind tables that can be used.
- const Shdr* arm_exidx_section =
- FindElfSectionByName<ElfClass>(".ARM.exidx", SHT_ARM_EXIDX,
- sections, names, names_end,
- elf_header->e_shnum);
- const Shdr* arm_extab_section =
- FindElfSectionByName<ElfClass>(".ARM.extab", SHT_PROGBITS,
- sections, names, names_end,
- elf_header->e_shnum);
- // Load information from these sections even if there is
- // .debug_info, because some functions (e.g., hand-written or
- // script-generated assembly) could have exidx entries but no DWARF.
- // (For functions with both, the DWARF info that has already been
- // parsed will take precedence.)
- if (arm_exidx_section && arm_extab_section && options.symbol_data != NO_CFI) {
- info->LoadedSection(".ARM.exidx");
- info->LoadedSection(".ARM.extab");
- bool result = LoadARMexidx<ElfClass>(elf_header,
- arm_exidx_section, arm_extab_section,
- loading_addr, module);
- found_usable_info = found_usable_info || result;
- }
-
- if (!found_debug_info_section) {
- fprintf(stderr, "%s: file contains no debugging information"
- " (no \".stab\" or \".debug_info\" sections)\n",
- obj_file.c_str());
-
- // Failed, but maybe there's a .gnu_debuglink section?
- if (read_gnu_debug_link) {
- const Shdr* gnu_debuglink_section
- = FindElfSectionByName<ElfClass>(".gnu_debuglink", SHT_PROGBITS,
- sections, names,
- names_end, elf_header->e_shnum);
- if (gnu_debuglink_section) {
- if (!info->debug_dirs().empty()) {
- const uint8_t *debuglink_contents =
- GetOffset<ElfClass, uint8_t>(elf_header,
- gnu_debuglink_section->sh_offset);
- string debuglink_file =
- ReadDebugLink(debuglink_contents,
- gnu_debuglink_section->sh_size,
- big_endian,
- obj_file,
- info->debug_dirs());
- info->set_debuglink_file(debuglink_file);
- } else {
- fprintf(stderr, ".gnu_debuglink section found in '%s', "
- "but no debug path specified.\n", obj_file.c_str());
- }
- } else {
- fprintf(stderr, "%s does not contain a .gnu_debuglink section.\n",
- obj_file.c_str());
- }
- } else {
- // Return true if some usable information was found, since the caller
- // doesn't want to use .gnu_debuglink.
- return found_usable_info;
- }
-
- // No debug info was found, let the user try again with .gnu_debuglink
- // if present.
- return false;
- }
-
- return true;
-}
-
-// Return the breakpad symbol file identifier for the architecture of
-// ELF_HEADER.
-template<typename ElfClass>
-const char* ElfArchitecture(const typename ElfClass::Ehdr* elf_header) {
- typedef typename ElfClass::Half Half;
- Half arch = elf_header->e_machine;
- switch (arch) {
- case EM_386: return "x86";
- case EM_ARM: return "arm";
- case EM_AARCH64: return "arm64";
- case EM_MIPS: return "mips";
- case EM_PPC64: return "ppc64";
- case EM_PPC: return "ppc";
- case EM_S390: return "s390";
- case EM_SPARC: return "sparc";
- case EM_SPARCV9: return "sparcv9";
- case EM_X86_64: return "x86_64";
- default: return NULL;
- }
-}
-
-// Return the non-directory portion of FILENAME: the portion after the
-// last slash, or the whole filename if there are no slashes.
-string BaseFileName(const string &filename) {
- // Lots of copies! basename's behavior is less than ideal.
- char* c_filename = strdup(filename.c_str());
- string base = basename(c_filename);
- free(c_filename);
- return base;
-}
-
-template<typename ElfClass>
-bool SanitizeDebugFile(const typename ElfClass::Ehdr* debug_elf_header,
- const string& debuglink_file,
- const string& obj_filename,
- const char* obj_file_architecture,
- const bool obj_file_is_big_endian) {
- const char* debug_architecture =
- ElfArchitecture<ElfClass>(debug_elf_header);
- if (!debug_architecture) {
- fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
- debuglink_file.c_str(), debug_elf_header->e_machine);
- return false;
- }
- if (strcmp(obj_file_architecture, debug_architecture)) {
- fprintf(stderr, "%s with ELF machine architecture %s does not match "
- "%s with ELF architecture %s\n",
- debuglink_file.c_str(), debug_architecture,
- obj_filename.c_str(), obj_file_architecture);
- return false;
- }
- bool debug_big_endian;
- if (!ElfEndianness<ElfClass>(debug_elf_header, &debug_big_endian))
- return false;
- if (debug_big_endian != obj_file_is_big_endian) {
- fprintf(stderr, "%s and %s does not match in endianness\n",
- obj_filename.c_str(), debuglink_file.c_str());
- return false;
- }
- return true;
-}
-
-template<typename ElfClass>
-bool InitModuleForElfClass(const typename ElfClass::Ehdr* elf_header,
- const string& obj_filename,
- scoped_ptr<Module>& module) {
- PageAllocator allocator;
- wasteful_vector<uint8_t> identifier(&allocator, kDefaultBuildIdSize);
- if (!FileID::ElfFileIdentifierFromMappedFile(elf_header, identifier)) {
- fprintf(stderr, "%s: unable to generate file identifier\n",
- obj_filename.c_str());
- return false;
- }
-
- const char *architecture = ElfArchitecture<ElfClass>(elf_header);
- if (!architecture) {
- fprintf(stderr, "%s: unrecognized ELF machine architecture: %d\n",
- obj_filename.c_str(), elf_header->e_machine);
- return false;
- }
-
- string name = BaseFileName(obj_filename);
- string os = "Linux";
- // Add an extra "0" at the end. PDB files on Windows have an 'age'
- // number appended to the end of the file identifier; this isn't
- // really used or necessary on other platforms, but be consistent.
- string id = FileID::ConvertIdentifierToUUIDString(identifier) + "0";
- // This is just the raw Build ID in hex.
- string code_id = FileID::ConvertIdentifierToString(identifier);
-
- module.reset(new Module(name, os, architecture, id, code_id));
-
- return true;
-}
-
-template<typename ElfClass>
-bool ReadSymbolDataElfClass(const typename ElfClass::Ehdr* elf_header,
- const string& obj_filename,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- Module** out_module) {
- typedef typename ElfClass::Ehdr Ehdr;
-
- *out_module = NULL;
-
- scoped_ptr<Module> module;
- if (!InitModuleForElfClass<ElfClass>(elf_header, obj_filename, module)) {
- return false;
- }
-
- // Figure out what endianness this file is.
- bool big_endian;
- if (!ElfEndianness<ElfClass>(elf_header, &big_endian))
- return false;
-
- LoadSymbolsInfo<ElfClass> info(debug_dirs);
- if (!LoadSymbols<ElfClass>(obj_filename, big_endian, elf_header,
- !debug_dirs.empty(), &info,
- options, module.get())) {
- const string debuglink_file = info.debuglink_file();
- if (debuglink_file.empty())
- return false;
-
- // Load debuglink ELF file.
- fprintf(stderr, "Found debugging info in %s\n", debuglink_file.c_str());
- MmapWrapper debug_map_wrapper;
- Ehdr* debug_elf_header = NULL;
- if (!LoadELF(debuglink_file, &debug_map_wrapper,
- reinterpret_cast<void**>(&debug_elf_header)) ||
- !SanitizeDebugFile<ElfClass>(debug_elf_header, debuglink_file,
- obj_filename,
- module->architecture().c_str(),
- big_endian)) {
- return false;
- }
-
- if (!LoadSymbols<ElfClass>(debuglink_file, big_endian,
- debug_elf_header, false, &info,
- options, module.get())) {
- return false;
- }
- }
-
- *out_module = module.release();
- return true;
-}
-
-} // namespace
-
-namespace google_breakpad {
-
-// Not explicitly exported, but not static so it can be used in unit tests.
-bool ReadSymbolDataInternal(const uint8_t* obj_file,
- const string& obj_filename,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- Module** module) {
- if (!IsValidElf(obj_file)) {
- fprintf(stderr, "Not a valid ELF file: %s\n", obj_filename.c_str());
- return false;
- }
-
- int elfclass = ElfClass(obj_file);
- if (elfclass == ELFCLASS32) {
- return ReadSymbolDataElfClass<ElfClass32>(
- reinterpret_cast<const Elf32_Ehdr*>(obj_file), obj_filename, debug_dirs,
- options, module);
- }
- if (elfclass == ELFCLASS64) {
- return ReadSymbolDataElfClass<ElfClass64>(
- reinterpret_cast<const Elf64_Ehdr*>(obj_file), obj_filename, debug_dirs,
- options, module);
- }
-
- return false;
-}
-
-bool WriteSymbolFile(const string &obj_file,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- std::ostream &sym_stream) {
- Module* module;
- if (!ReadSymbolData(obj_file, debug_dirs, options, &module))
- return false;
-
- bool result = module->Write(sym_stream, options.symbol_data);
- delete module;
- return result;
-}
-
-// Read the selected object file's debugging information, and write out the
-// header only to |stream|. Return true on success; if an error occurs, report
-// it and return false.
-bool WriteSymbolFileHeader(const string& obj_file,
- std::ostream &sym_stream) {
- MmapWrapper map_wrapper;
- void* elf_header = NULL;
- if (!LoadELF(obj_file, &map_wrapper, &elf_header)) {
- fprintf(stderr, "Could not load ELF file: %s\n", obj_file.c_str());
- return false;
- }
-
- if (!IsValidElf(elf_header)) {
- fprintf(stderr, "Not a valid ELF file: %s\n", obj_file.c_str());
- return false;
- }
-
- int elfclass = ElfClass(elf_header);
- scoped_ptr<Module> module;
- if (elfclass == ELFCLASS32) {
- if (!InitModuleForElfClass<ElfClass32>(
- reinterpret_cast<const Elf32_Ehdr*>(elf_header), obj_file, module)) {
- fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
- return false;
- }
- } else if (elfclass == ELFCLASS64) {
- if (!InitModuleForElfClass<ElfClass64>(
- reinterpret_cast<const Elf64_Ehdr*>(elf_header), obj_file, module)) {
- fprintf(stderr, "Failed to load ELF module: %s\n", obj_file.c_str());
- return false;
- }
- } else {
- fprintf(stderr, "Unsupported module file: %s\n", obj_file.c_str());
- return false;
- }
-
- return module->Write(sym_stream, ALL_SYMBOL_DATA);
-}
-
-bool ReadSymbolData(const string& obj_file,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- Module** module) {
- MmapWrapper map_wrapper;
- void* elf_header = NULL;
- if (!LoadELF(obj_file, &map_wrapper, &elf_header))
- return false;
-
- return ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(elf_header),
- obj_file, debug_dirs, options, module);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
deleted file mode 100644
index 1f204cbad..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// dump_symbols.h: Read debugging information from an ELF file, and write
-// it out as a Breakpad symbol file.
-
-#ifndef COMMON_LINUX_DUMP_SYMBOLS_H__
-#define COMMON_LINUX_DUMP_SYMBOLS_H__
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "common/symbol_data.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-class Module;
-
-struct DumpOptions {
- DumpOptions(SymbolData symbol_data, bool handle_inter_cu_refs)
- : symbol_data(symbol_data),
- handle_inter_cu_refs(handle_inter_cu_refs) {
- }
-
- SymbolData symbol_data;
- bool handle_inter_cu_refs;
-};
-
-// Find all the debugging information in OBJ_FILE, an ELF executable
-// or shared library, and write it to SYM_STREAM in the Breakpad symbol
-// file format.
-// If OBJ_FILE has been stripped but contains a .gnu_debuglink section,
-// then look for the debug file in DEBUG_DIRS.
-// SYMBOL_DATA allows limiting the type of symbol data written.
-bool WriteSymbolFile(const string &obj_file,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- std::ostream &sym_stream);
-
-// Read the selected object file's debugging information, and write out the
-// header only to |stream|. Return true on success; if an error occurs, report
-// it and return false.
-bool WriteSymbolFileHeader(const string& obj_file,
- std::ostream &sym_stream);
-
-// As above, but simply return the debugging information in MODULE
-// instead of writing it to a stream. The caller owns the resulting
-// Module object and must delete it when finished.
-bool ReadSymbolData(const string& obj_file,
- const std::vector<string>& debug_dirs,
- const DumpOptions& options,
- Module** module);
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_DUMP_SYMBOLS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc
deleted file mode 100644
index bb7b20076..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/dump_symbols_unittest.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-// dump_symbols_unittest.cc:
-// Unittests for google_breakpad::DumpSymbols
-
-#include <elf.h>
-#include <link.h>
-#include <stdio.h>
-
-#include <sstream>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/elf_gnu_compat.h"
-#include "common/linux/elfutils.h"
-#include "common/linux/dump_symbols.h"
-#include "common/linux/synth_elf.h"
-#include "common/module.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-bool ReadSymbolDataInternal(const uint8_t* obj_file,
- const string& obj_filename,
- const std::vector<string>& debug_dir,
- const DumpOptions& options,
- Module** module);
-
-using google_breakpad::synth_elf::ELF;
-using google_breakpad::synth_elf::Notes;
-using google_breakpad::synth_elf::StringTable;
-using google_breakpad::synth_elf::SymbolTable;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Section;
-using std::stringstream;
-using std::vector;
-using ::testing::Test;
-using ::testing::Types;
-
-template<typename ElfClass>
-class DumpSymbols : public Test {
- public:
- void GetElfContents(ELF& elf) {
- string contents;
- ASSERT_TRUE(elf.GetContents(&contents));
- ASSERT_LT(0U, contents.size());
-
- elfdata_v.clear();
- elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end());
- elfdata = &elfdata_v[0];
- }
-
- vector<uint8_t> elfdata_v;
- uint8_t* elfdata;
-};
-
-typedef Types<ElfClass32, ElfClass64> ElfClasses;
-
-TYPED_TEST_CASE(DumpSymbols, ElfClasses);
-
-TYPED_TEST(DumpSymbols, Invalid) {
- Elf32_Ehdr header;
- memset(&header, 0, sizeof(header));
- Module* module;
- DumpOptions options(ALL_SYMBOL_DATA, true);
- EXPECT_FALSE(ReadSymbolDataInternal(reinterpret_cast<uint8_t*>(&header),
- "foo",
- vector<string>(),
- options,
- &module));
-}
-
-TYPED_TEST(DumpSymbols, SimplePublic) {
- ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
- // Zero out text section for simplicity.
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
-
- // Add a public symbol.
- StringTable table(kLittleEndian);
- SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table);
- syms.AddSymbol("superfunc",
- (typename TypeParam::Addr)0x1000,
- (typename TypeParam::Addr)0x10,
- // ELF32_ST_INFO works for 32-or 64-bit.
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- SHN_UNDEF + 1);
- int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
- elf.AddSection(".dynsym", syms,
- SHT_DYNSYM, // type
- SHF_ALLOC, // flags
- 0, // addr
- index, // link
- sizeof(typename TypeParam::Sym)); // entsize
-
- elf.Finish();
- this->GetElfContents(elf);
-
- Module* module;
- DumpOptions options(ALL_SYMBOL_DATA, true);
- EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
- "foo",
- vector<string>(),
- options,
- &module));
-
- stringstream s;
- module->Write(s, ALL_SYMBOL_DATA);
- const string expected =
- string("MODULE Linux ") + TypeParam::kMachineName
- + " 000000000000000000000000000000000 foo\n"
- "INFO CODE_ID 00000000000000000000000000000000\n"
- "PUBLIC 1000 0 superfunc\n";
- EXPECT_EQ(expected, s.str());
- delete module;
-}
-
-TYPED_TEST(DumpSymbols, SimpleBuildID) {
- ELF elf(TypeParam::kMachine, TypeParam::kClass, kLittleEndian);
- // Zero out text section for simplicity.
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
-
- // Add a Build ID
- const uint8_t kExpectedIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13};
- Notes notes(kLittleEndian);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
- sizeof(kExpectedIdentifierBytes));
- elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
-
- // Add a public symbol.
- StringTable table(kLittleEndian);
- SymbolTable syms(kLittleEndian, TypeParam::kAddrSize, table);
- syms.AddSymbol("superfunc",
- (typename TypeParam::Addr)0x1000,
- (typename TypeParam::Addr)0x10,
- // ELF32_ST_INFO works for 32-or 64-bit.
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- SHN_UNDEF + 1);
- int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
- elf.AddSection(".dynsym", syms,
- SHT_DYNSYM, // type
- SHF_ALLOC, // flags
- 0, // addr
- index, // link
- sizeof(typename TypeParam::Sym)); // entsize
-
- elf.Finish();
- this->GetElfContents(elf);
-
- Module* module;
- DumpOptions options(ALL_SYMBOL_DATA, true);
- EXPECT_TRUE(ReadSymbolDataInternal(this->elfdata,
- "foo",
- vector<string>(),
- options,
- &module));
-
- stringstream s;
- module->Write(s, ALL_SYMBOL_DATA);
- const string expected =
- string("MODULE Linux ") + TypeParam::kMachineName
- + " 030201000504070608090A0B0C0D0E0F0 foo\n"
- "INFO CODE_ID 000102030405060708090A0B0C0D0E0F10111213\n"
- "PUBLIC 1000 0 superfunc\n";
- EXPECT_EQ(expected, s.str());
- delete module;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h
deleted file mode 100644
index 3f1d18481..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/eintr_wrapper.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 COMMON_LINUX_EINTR_WRAPPER_H_
-#define COMMON_LINUX_EINTR_WRAPPER_H_
-
-#include <errno.h>
-
-// This provides a wrapper around system calls which may be interrupted by a
-// signal and return EINTR. See man 7 signal.
-//
-
-#define HANDLE_EINTR(x) ({ \
- __typeof__(x) eintr_wrapper_result; \
- do { \
- eintr_wrapper_result = (x); \
- } while (eintr_wrapper_result == -1 && errno == EINTR); \
- eintr_wrapper_result; \
-})
-
-#define IGNORE_EINTR(x) ({ \
- __typeof__(x) eintr_wrapper_result; \
- do { \
- eintr_wrapper_result = (x); \
- if (eintr_wrapper_result == -1 && errno == EINTR) { \
- eintr_wrapper_result = 0; \
- } \
- } while (0); \
- eintr_wrapper_result; \
-})
-
-#endif // COMMON_LINUX_EINTR_WRAPPER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc
deleted file mode 100644
index 0e7db7b1f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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.
-
-// elf_core_dump.cc: Implement google_breakpad::ElfCoreDump.
-// See elf_core_dump.h for details.
-
-#include "common/linux/elf_core_dump.h"
-
-#include <stddef.h>
-#include <string.h>
-
-namespace google_breakpad {
-
-// Implementation of ElfCoreDump::Note.
-
-ElfCoreDump::Note::Note() {}
-
-ElfCoreDump::Note::Note(const MemoryRange& content) : content_(content) {}
-
-bool ElfCoreDump::Note::IsValid() const {
- return GetHeader() != NULL;
-}
-
-const ElfCoreDump::Nhdr* ElfCoreDump::Note::GetHeader() const {
- return content_.GetData<Nhdr>(0);
-}
-
-ElfCoreDump::Word ElfCoreDump::Note::GetType() const {
- const Nhdr* header = GetHeader();
- // 0 is not being used as a NOTE type.
- return header ? header->n_type : 0;
-}
-
-MemoryRange ElfCoreDump::Note::GetName() const {
- const Nhdr* header = GetHeader();
- if (header) {
- return content_.Subrange(sizeof(Nhdr), header->n_namesz);
- }
- return MemoryRange();
-}
-
-MemoryRange ElfCoreDump::Note::GetDescription() const {
- const Nhdr* header = GetHeader();
- if (header) {
- return content_.Subrange(AlignedSize(sizeof(Nhdr) + header->n_namesz),
- header->n_descsz);
- }
- return MemoryRange();
-}
-
-ElfCoreDump::Note ElfCoreDump::Note::GetNextNote() const {
- MemoryRange next_content;
- const Nhdr* header = GetHeader();
- if (header) {
- size_t next_offset = AlignedSize(sizeof(Nhdr) + header->n_namesz);
- next_offset = AlignedSize(next_offset + header->n_descsz);
- next_content =
- content_.Subrange(next_offset, content_.length() - next_offset);
- }
- return Note(next_content);
-}
-
-// static
-size_t ElfCoreDump::Note::AlignedSize(size_t size) {
- size_t mask = sizeof(Word) - 1;
- return (size + mask) & ~mask;
-}
-
-
-// Implementation of ElfCoreDump.
-
-ElfCoreDump::ElfCoreDump() {}
-
-ElfCoreDump::ElfCoreDump(const MemoryRange& content)
- : content_(content) {
-}
-
-void ElfCoreDump::SetContent(const MemoryRange& content) {
- content_ = content;
-}
-
-bool ElfCoreDump::IsValid() const {
- const Ehdr* header = GetHeader();
- return (header &&
- header->e_ident[0] == ELFMAG0 &&
- header->e_ident[1] == ELFMAG1 &&
- header->e_ident[2] == ELFMAG2 &&
- header->e_ident[3] == ELFMAG3 &&
- header->e_ident[4] == kClass &&
- header->e_version == EV_CURRENT &&
- header->e_type == ET_CORE);
-}
-
-const ElfCoreDump::Ehdr* ElfCoreDump::GetHeader() const {
- return content_.GetData<Ehdr>(0);
-}
-
-const ElfCoreDump::Phdr* ElfCoreDump::GetProgramHeader(unsigned index) const {
- const Ehdr* header = GetHeader();
- if (header) {
- return reinterpret_cast<const Phdr*>(content_.GetArrayElement(
- header->e_phoff, header->e_phentsize, index));
- }
- return NULL;
-}
-
-const ElfCoreDump::Phdr* ElfCoreDump::GetFirstProgramHeaderOfType(
- Word type) const {
- for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
- const Phdr* program = GetProgramHeader(i);
- if (program->p_type == type) {
- return program;
- }
- }
- return NULL;
-}
-
-unsigned ElfCoreDump::GetProgramHeaderCount() const {
- const Ehdr* header = GetHeader();
- return header ? header->e_phnum : 0;
-}
-
-bool ElfCoreDump::CopyData(void* buffer, Addr virtual_address, size_t length) {
- for (unsigned i = 0, n = GetProgramHeaderCount(); i < n; ++i) {
- const Phdr* program = GetProgramHeader(i);
- if (program->p_type != PT_LOAD)
- continue;
-
- size_t offset_in_segment = virtual_address - program->p_vaddr;
- if (virtual_address >= program->p_vaddr &&
- offset_in_segment < program->p_filesz) {
- const void* data =
- content_.GetData(program->p_offset + offset_in_segment, length);
- if (data) {
- memcpy(buffer, data, length);
- return true;
- }
- }
- }
- return false;
-}
-
-ElfCoreDump::Note ElfCoreDump::GetFirstNote() const {
- MemoryRange note_content;
- const Phdr* program_header = GetFirstProgramHeaderOfType(PT_NOTE);
- if (program_header) {
- note_content = content_.Subrange(program_header->p_offset,
- program_header->p_filesz);
- }
- return Note(note_content);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h
deleted file mode 100644
index d03c7a88d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// 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.
-
-// elf_core_dump.h: Define the google_breakpad::ElfCoreDump class, which
-// encapsulates an ELF core dump file mapped into memory.
-
-#ifndef COMMON_LINUX_ELF_CORE_DUMP_H_
-#define COMMON_LINUX_ELF_CORE_DUMP_H_
-
-#include <elf.h>
-#include <link.h>
-#include <stddef.h>
-
-#include "common/memory_range.h"
-
-namespace google_breakpad {
-
-// A class encapsulating an ELF core dump file mapped into memory, which
-// provides methods for accessing program headers and the note section.
-class ElfCoreDump {
- public:
- // ELF types based on the value of __WORDSIZE.
- typedef ElfW(Ehdr) Ehdr;
- typedef ElfW(Nhdr) Nhdr;
- typedef ElfW(Phdr) Phdr;
- typedef ElfW(Word) Word;
- typedef ElfW(Addr) Addr;
-#if __WORDSIZE == 32
- static const int kClass = ELFCLASS32;
-#elif __WORDSIZE == 64
- static const int kClass = ELFCLASS64;
-#else
-#error "Unsupported __WORDSIZE for ElfCoreDump."
-#endif
-
- // A class encapsulating the note content in a core dump, which provides
- // methods for accessing the name and description of a note.
- class Note {
- public:
- Note();
-
- // Constructor that takes the note content from |content|.
- explicit Note(const MemoryRange& content);
-
- // Returns true if this note is valid, i,e. a note header is found in
- // |content_|, or false otherwise.
- bool IsValid() const;
-
- // Returns the note header, or NULL if no note header is found in
- // |content_|.
- const Nhdr* GetHeader() const;
-
- // Returns the note type, or 0 if no note header is found in |content_|.
- Word GetType() const;
-
- // Returns a memory range covering the note name, or an empty range
- // if no valid note name is found in |content_|.
- MemoryRange GetName() const;
-
- // Returns a memory range covering the note description, or an empty
- // range if no valid note description is found in |content_|.
- MemoryRange GetDescription() const;
-
- // Returns the note following this note, or an empty note if no valid
- // note is found after this note.
- Note GetNextNote() const;
-
- private:
- // Returns the size in bytes round up to the word alignment, specified
- // for the note section, of a given size in bytes.
- static size_t AlignedSize(size_t size);
-
- // Note content.
- MemoryRange content_;
- };
-
- ElfCoreDump();
-
- // Constructor that takes the core dump content from |content|.
- explicit ElfCoreDump(const MemoryRange& content);
-
- // Sets the core dump content to |content|.
- void SetContent(const MemoryRange& content);
-
- // Returns true if a valid ELF header in the core dump, or false otherwise.
- bool IsValid() const;
-
- // Returns the ELF header in the core dump, or NULL if no ELF header
- // is found in |content_|.
- const Ehdr* GetHeader() const;
-
- // Returns the |index|-th program header in the core dump, or NULL if no
- // ELF header is found in |content_| or |index| is out of bounds.
- const Phdr* GetProgramHeader(unsigned index) const;
-
- // Returns the first program header of |type| in the core dump, or NULL if
- // no ELF header is found in |content_| or no program header of |type| is
- // found.
- const Phdr* GetFirstProgramHeaderOfType(Word type) const;
-
- // Returns the number of program headers in the core dump, or 0 if no
- // ELF header is found in |content_|.
- unsigned GetProgramHeaderCount() const;
-
- // Copies |length| bytes of data starting at |virtual_address| in the core
- // dump to |buffer|. |buffer| should be a valid pointer to a buffer of at
- // least |length| bytes. Returns true if the data to be copied is found in
- // the core dump, or false otherwise.
- bool CopyData(void* buffer, Addr virtual_address, size_t length);
-
- // Returns the first note found in the note section of the core dump, or
- // an empty note if no note is found.
- Note GetFirstNote() const;
-
- private:
- // Core dump content.
- MemoryRange content_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_ELF_CORE_DUMP_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc
deleted file mode 100644
index 9b41dceee..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_core_dump_unittest.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-// 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.
-
-// elf_core_dump_unittest.cc: Unit tests for google_breakpad::ElfCoreDump.
-
-#include <sys/procfs.h>
-
-#include <set>
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/elf_core_dump.h"
-#include "common/linux/memory_mapped_file.h"
-#include "common/tests/file_utils.h"
-#include "common/linux/tests/crash_generator.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::AutoTempDir;
-using google_breakpad::CrashGenerator;
-using google_breakpad::ElfCoreDump;
-using google_breakpad::MemoryMappedFile;
-using google_breakpad::MemoryRange;
-using google_breakpad::WriteFile;
-using std::set;
-
-TEST(ElfCoreDumpTest, DefaultConstructor) {
- ElfCoreDump core;
- EXPECT_FALSE(core.IsValid());
- EXPECT_EQ(NULL, core.GetHeader());
- EXPECT_EQ(0U, core.GetProgramHeaderCount());
- EXPECT_EQ(NULL, core.GetProgramHeader(0));
- EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD));
- EXPECT_FALSE(core.GetFirstNote().IsValid());
-}
-
-TEST(ElfCoreDumpTest, TestElfHeader) {
- ElfCoreDump::Ehdr header;
- memset(&header, 0, sizeof(header));
-
- AutoTempDir temp_dir;
- string core_path = temp_dir.path() + "/core";
- const char* core_file = core_path.c_str();
- MemoryMappedFile mapped_core_file;
- ElfCoreDump core;
-
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header) - 1));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
- EXPECT_EQ(NULL, core.GetHeader());
- EXPECT_EQ(0U, core.GetProgramHeaderCount());
- EXPECT_EQ(NULL, core.GetProgramHeader(0));
- EXPECT_EQ(NULL, core.GetFirstProgramHeaderOfType(PT_LOAD));
- EXPECT_FALSE(core.GetFirstNote().IsValid());
-
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_ident[0] = ELFMAG0;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_ident[1] = ELFMAG1;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_ident[2] = ELFMAG2;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_ident[3] = ELFMAG3;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_ident[4] = ElfCoreDump::kClass;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_version = EV_CURRENT;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_FALSE(core.IsValid());
-
- header.e_type = ET_CORE;
- ASSERT_TRUE(WriteFile(core_file, &header, sizeof(header)));
- ASSERT_TRUE(mapped_core_file.Map(core_file, 0));
- core.SetContent(mapped_core_file.content());
- EXPECT_TRUE(core.IsValid());
-}
-
-TEST(ElfCoreDumpTest, ValidCoreFile) {
- CrashGenerator crash_generator;
- if (!crash_generator.HasDefaultCorePattern()) {
- fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped "
- "due to non-default core pattern");
- return;
- }
-
- const unsigned kNumOfThreads = 3;
- const unsigned kCrashThread = 1;
- const int kCrashSignal = SIGABRT;
- ASSERT_TRUE(crash_generator.CreateChildCrash(kNumOfThreads, kCrashThread,
- kCrashSignal, NULL));
- pid_t expected_crash_thread_id = crash_generator.GetThreadId(kCrashThread);
- set<pid_t> expected_thread_ids;
- for (unsigned i = 0; i < kNumOfThreads; ++i) {
- expected_thread_ids.insert(crash_generator.GetThreadId(i));
- }
-
-#if defined(__ANDROID__)
- struct stat st;
- if (stat(crash_generator.GetCoreFilePath().c_str(), &st) != 0) {
- fprintf(stderr, "ElfCoreDumpTest.ValidCoreFile test is skipped "
- "due to no core file being generated");
- return;
- }
-#endif
-
- MemoryMappedFile mapped_core_file;
- ASSERT_TRUE(
- mapped_core_file.Map(crash_generator.GetCoreFilePath().c_str(), 0));
-
- ElfCoreDump core;
- core.SetContent(mapped_core_file.content());
- EXPECT_TRUE(core.IsValid());
-
- // Based on write_note_info() in linux/kernel/fs/binfmt_elf.c, notes are
- // ordered as follows (NT_PRXFPREG and NT_386_TLS are i386 specific):
- // Thread Name Type
- // -------------------------------------------------------------------
- // 1st thread CORE NT_PRSTATUS
- // process-wide CORE NT_PRPSINFO
- // process-wide CORE NT_AUXV
- // 1st thread CORE NT_FPREGSET
- // 1st thread LINUX NT_PRXFPREG
- // 1st thread LINUX NT_386_TLS
- //
- // 2nd thread CORE NT_PRSTATUS
- // 2nd thread CORE NT_FPREGSET
- // 2nd thread LINUX NT_PRXFPREG
- // 2nd thread LINUX NT_386_TLS
- //
- // 3rd thread CORE NT_PRSTATUS
- // 3rd thread CORE NT_FPREGSET
- // 3rd thread LINUX NT_PRXFPREG
- // 3rd thread LINUX NT_386_TLS
-
- size_t num_nt_prpsinfo = 0;
- size_t num_nt_prstatus = 0;
- size_t num_pr_fpvalid = 0;
-#if defined(__i386__) || defined(__x86_64__)
- size_t num_nt_fpregset = 0;
-#endif
-#if defined(__i386__)
- size_t num_nt_prxfpreg = 0;
-#endif
- set<pid_t> actual_thread_ids;
- ElfCoreDump::Note note = core.GetFirstNote();
- while (note.IsValid()) {
- MemoryRange name = note.GetName();
- MemoryRange description = note.GetDescription();
- EXPECT_FALSE(name.IsEmpty());
- EXPECT_FALSE(description.IsEmpty());
-
- switch (note.GetType()) {
- case NT_PRPSINFO: {
- EXPECT_TRUE(description.data() != NULL);
- EXPECT_EQ(sizeof(elf_prpsinfo), description.length());
- ++num_nt_prpsinfo;
- break;
- }
- case NT_PRSTATUS: {
- EXPECT_TRUE(description.data() != NULL);
- EXPECT_EQ(sizeof(elf_prstatus), description.length());
- const elf_prstatus* status = description.GetData<elf_prstatus>(0);
- actual_thread_ids.insert(status->pr_pid);
- if (num_nt_prstatus == 0) {
- EXPECT_EQ(expected_crash_thread_id, status->pr_pid);
- EXPECT_EQ(kCrashSignal, status->pr_info.si_signo);
- }
- ++num_nt_prstatus;
- if (status->pr_fpvalid)
- ++num_pr_fpvalid;
- break;
- }
-#if defined(__i386__) || defined(__x86_64__)
- case NT_FPREGSET: {
- EXPECT_TRUE(description.data() != NULL);
- EXPECT_EQ(sizeof(user_fpregs_struct), description.length());
- ++num_nt_fpregset;
- break;
- }
-#endif
-#if defined(__i386__)
- case NT_PRXFPREG: {
- EXPECT_TRUE(description.data() != NULL);
- EXPECT_EQ(sizeof(user_fpxregs_struct), description.length());
- ++num_nt_prxfpreg;
- break;
- }
-#endif
- default:
- break;
- }
- note = note.GetNextNote();
- }
-
- EXPECT_TRUE(expected_thread_ids == actual_thread_ids);
- EXPECT_EQ(1U, num_nt_prpsinfo);
- EXPECT_EQ(kNumOfThreads, num_nt_prstatus);
-#if defined(__i386__) || defined(__x86_64__)
- EXPECT_EQ(num_pr_fpvalid, num_nt_fpregset);
-#endif
-#if defined(__i386__)
- EXPECT_EQ(num_pr_fpvalid, num_nt_prxfpreg);
-#endif
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h
deleted file mode 100644
index f870cbc7d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_gnu_compat.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// -*- mode: C++ -*-
-
-// Copyright (c) 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.
-
-// Original author: Lei Zhang <thestig@google.com>
-
-// elf_gnu_compat.h: #defines unique to glibc's elf.h.
-
-#ifndef COMMON_LINUX_ELF_GNU_COMPAT_H_
-#define COMMON_LINUX_ELF_GNU_COMPAT_H_
-
-#include <elf.h>
-
-// A note type on GNU systems corresponding to the .note.gnu.build-id section.
-#ifndef NT_GNU_BUILD_ID
-#define NT_GNU_BUILD_ID 3
-#endif
-
-#endif // COMMON_LINUX_ELF_GNU_COMPAT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc
deleted file mode 100644
index 562875e11..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.cc
+++ /dev/null
@@ -1,178 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-#include "common/linux/elf_symbols_to_module.h"
-
-#include <cxxabi.h>
-#include <elf.h>
-#include <string.h>
-
-#include "common/byte_cursor.h"
-#include "common/module.h"
-
-namespace google_breakpad {
-
-class ELFSymbolIterator {
-public:
- // The contents of an ELF symbol, adjusted for the host's endianness,
- // word size, and so on. Corresponds to the data in Elf32_Sym / Elf64_Sym.
- struct Symbol {
- // True if this iterator has reached the end of the symbol array. When
- // this is set, the other members of this structure are not valid.
- bool at_end;
-
- // The number of this symbol within the list.
- size_t index;
-
- // The current symbol's name offset. This is the offset within the
- // string table.
- size_t name_offset;
-
- // The current symbol's value, size, info and shndx fields.
- uint64_t value;
- uint64_t size;
- unsigned char info;
- uint16_t shndx;
- };
-
- // Create an ELFSymbolIterator walking the symbols in BUFFER. Treat the
- // symbols as big-endian if BIG_ENDIAN is true, as little-endian
- // otherwise. Assume each symbol has a 'value' field whose size is
- // VALUE_SIZE.
- //
- ELFSymbolIterator(const ByteBuffer *buffer, bool big_endian,
- size_t value_size)
- : value_size_(value_size), cursor_(buffer, big_endian) {
- // Actually, weird sizes could be handled just fine, but they're
- // probably mistakes --- expressed in bits, say.
- assert(value_size == 4 || value_size == 8);
- symbol_.index = 0;
- Fetch();
- }
-
- // Move to the next symbol. This function's behavior is undefined if
- // at_end() is true when it is called.
- ELFSymbolIterator &operator++() { Fetch(); symbol_.index++; return *this; }
-
- // Dereferencing this iterator produces a reference to an Symbol structure
- // that holds the current symbol's values. The symbol is owned by this
- // SymbolIterator, and will be invalidated at the next call to operator++.
- const Symbol &operator*() const { return symbol_; }
- const Symbol *operator->() const { return &symbol_; }
-
-private:
- // Read the symbol at cursor_, and set symbol_ appropriately.
- void Fetch() {
- // Elf32_Sym and Elf64_Sym have different layouts.
- unsigned char other;
- if (value_size_ == 4) {
- // Elf32_Sym
- cursor_
- .Read(4, false, &symbol_.name_offset)
- .Read(4, false, &symbol_.value)
- .Read(4, false, &symbol_.size)
- .Read(1, false, &symbol_.info)
- .Read(1, false, &other)
- .Read(2, false, &symbol_.shndx);
- } else {
- // Elf64_Sym
- cursor_
- .Read(4, false, &symbol_.name_offset)
- .Read(1, false, &symbol_.info)
- .Read(1, false, &other)
- .Read(2, false, &symbol_.shndx)
- .Read(8, false, &symbol_.value)
- .Read(8, false, &symbol_.size);
- }
- symbol_.at_end = !cursor_;
- }
-
- // The size of symbols' value field, in bytes.
- size_t value_size_;
-
- // A byte cursor traversing buffer_.
- ByteCursor cursor_;
-
- // Values for the symbol this iterator refers to.
- Symbol symbol_;
-};
-
-const char *SymbolString(ptrdiff_t offset, ByteBuffer& strings) {
- if (offset < 0 || (size_t) offset >= strings.Size()) {
- // Return the null string.
- offset = 0;
- }
- return reinterpret_cast<const char *>(strings.start + offset);
-}
-
-bool ELFSymbolsToModule(const uint8_t *symtab_section,
- size_t symtab_size,
- const uint8_t *string_section,
- size_t string_size,
- const bool big_endian,
- size_t value_size,
- Module *module) {
- ByteBuffer symbols(symtab_section, symtab_size);
- // Ensure that the string section is null-terminated.
- if (string_section[string_size - 1] != '\0') {
- const void* null_terminator = memrchr(string_section, '\0', string_size);
- string_size = reinterpret_cast<const uint8_t*>(null_terminator)
- - string_section;
- }
- ByteBuffer strings(string_section, string_size);
-
- // The iterator walking the symbol table.
- ELFSymbolIterator iterator(&symbols, big_endian, value_size);
-
- while(!iterator->at_end) {
- if (ELF32_ST_TYPE(iterator->info) == STT_FUNC &&
- iterator->shndx != SHN_UNDEF) {
- Module::Extern *ext = new Module::Extern(iterator->value);
- ext->name = SymbolString(iterator->name_offset, strings);
-#if !defined(__ANDROID__) // Android NDK doesn't provide abi::__cxa_demangle.
- int status = 0;
- char* demangled =
- abi::__cxa_demangle(ext->name.c_str(), NULL, NULL, &status);
- if (demangled) {
- if (status == 0)
- ext->name = demangled;
- free(demangled);
- }
-#endif
- module->AddExtern(ext);
- }
- ++iterator;
- }
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h
deleted file mode 100644
index 2e7c09715..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-// elf_symbols_to_module.h: Exposes ELFSymbolsToModule, a function
-// for reading ELF symbol tables and inserting exported symbol names
-// into a google_breakpad::Module as Extern definitions.
-
-#ifndef BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
-#define BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-namespace google_breakpad {
-
-class Module;
-
-bool ELFSymbolsToModule(const uint8_t *symtab_section,
- size_t symtab_size,
- const uint8_t *string_section,
- size_t string_size,
- const bool big_endian,
- size_t value_size,
- Module *module);
-
-} // namespace google_breakpad
-
-
-#endif // BREAKPAD_COMMON_LINUX_ELF_SYMBOLS_TO_MODULE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc
deleted file mode 100644
index 8984449ab..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elf_symbols_to_module_unittest.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-// elf_symbols_to_module_unittest.cc:
-// Unittests for google_breakpad::ELFSymbolsToModule
-
-#include <elf.h>
-
-#include <string>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/elf_symbols_to_module.h"
-#include "common/linux/synth_elf.h"
-#include "common/module.h"
-#include "common/test_assembler.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::Module;
-using google_breakpad::synth_elf::StringTable;
-using google_breakpad::test_assembler::Endianness;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::Section;
-using ::testing::Test;
-using ::testing::TestWithParam;
-using std::vector;
-
-class ELFSymbolsToModuleTestFixture {
-public:
- ELFSymbolsToModuleTestFixture(Endianness endianness,
- size_t value_size) : module("a", "b", "c", "d"),
- section(endianness),
- table(endianness),
- value_size(value_size) {}
-
- bool ProcessSection() {
- string section_contents, table_contents;
- section.GetContents(&section_contents);
- table.GetContents(&table_contents);
-
- bool ret = ELFSymbolsToModule(reinterpret_cast<const uint8_t*>(section_contents.data()),
- section_contents.size(),
- reinterpret_cast<const uint8_t*>(table_contents.data()),
- table_contents.size(),
- section.endianness() == kBigEndian,
- value_size,
- &module);
- module.GetExterns(&externs, externs.end());
- return ret;
- }
-
- Module module;
- Section section;
- StringTable table;
- string section_contents;
- // 4 or 8 (bytes)
- size_t value_size;
-
- vector<Module::Extern *> externs;
-};
-
-class ELFSymbolsToModuleTest32 : public ELFSymbolsToModuleTestFixture,
- public TestWithParam<Endianness> {
-public:
- ELFSymbolsToModuleTest32() : ELFSymbolsToModuleTestFixture(GetParam(), 4) {}
-
- void AddElf32Sym(const string& name, uint32_t value,
- uint32_t size, unsigned info, uint16_t shndx) {
- section
- .D32(table.Add(name))
- .D32(value)
- .D32(size)
- .D8(info)
- .D8(0) // other
- .D16(shndx);
- }
-};
-
-TEST_P(ELFSymbolsToModuleTest32, NoFuncs) {
- ProcessSection();
-
- ASSERT_EQ((size_t)0, externs.size());
-}
-
-TEST_P(ELFSymbolsToModuleTest32, OneFunc) {
- const string kFuncName = "superfunc";
- const uint32_t kFuncAddr = 0x1000;
- const uint32_t kFuncSize = 0x10;
-
- AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest32, NameOutOfBounds) {
- const string kFuncName = "";
- const uint32_t kFuncAddr = 0x1000;
- const uint32_t kFuncSize = 0x10;
-
- table.Add("Foo");
- table.Add("Bar");
- // Can't use AddElf32Sym because it puts in a valid string offset.
- section
- .D32((uint32_t)table.Here().Value() + 1)
- .D32(kFuncAddr)
- .D32(kFuncSize)
- .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
- .D8(0) // other
- .D16(SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest32, NonTerminatedStringTable) {
- const string kFuncName = "";
- const uint32_t kFuncAddr = 0x1000;
- const uint32_t kFuncSize = 0x10;
-
- table.Add("Foo");
- table.Add("Bar");
- // Add a non-null-terminated string to the end of the string table
- Label l;
- table
- .Mark(&l)
- .Append("Unterminated");
- // Can't use AddElf32Sym because it puts in a valid string offset.
- section
- .D32((uint32_t)l.Value())
- .D32(kFuncAddr)
- .D32(kFuncSize)
- .D8(ELF32_ST_INFO(STB_GLOBAL, STT_FUNC))
- .D8(0) // other
- .D16(SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest32, MultipleFuncs) {
- const string kFuncName1 = "superfunc";
- const uint32_t kFuncAddr1 = 0x10001000;
- const uint32_t kFuncSize1 = 0x10;
- const string kFuncName2 = "awesomefunc";
- const uint32_t kFuncAddr2 = 0x20002000;
- const uint32_t kFuncSize2 = 0x2f;
- const string kFuncName3 = "megafunc";
- const uint32_t kFuncAddr3 = 0x30003000;
- const uint32_t kFuncSize3 = 0x3c;
-
- AddElf32Sym(kFuncName1, kFuncAddr1, kFuncSize1,
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
- AddElf32Sym(kFuncName2, kFuncAddr2, kFuncSize2,
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 2);
- AddElf32Sym(kFuncName3, kFuncAddr3, kFuncSize3,
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 3);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)3, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName1, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
- Module::Extern *extern2 = externs[1];
- EXPECT_EQ(kFuncName2, extern2->name);
- EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
- Module::Extern *extern3 = externs[2];
- EXPECT_EQ(kFuncName3, extern3->name);
- EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest32, SkipStuff) {
- const string kFuncName = "superfunc";
- const uint32_t kFuncAddr = 0x1000;
- const uint32_t kFuncSize = 0x10;
-
- // Should skip functions in SHN_UNDEF
- AddElf32Sym("skipme", 0xFFFF, 0x10,
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- SHN_UNDEF);
- AddElf32Sym(kFuncName, kFuncAddr, kFuncSize,
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
- // Should skip non-STT_FUNC entries.
- AddElf32Sym("skipmetoo", 0xAAAA, 0x10,
- ELF32_ST_INFO(STB_GLOBAL, STT_FILE),
- SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-// Run all the 32-bit tests with both endianness
-INSTANTIATE_TEST_CASE_P(Endian,
- ELFSymbolsToModuleTest32,
- ::testing::Values(kLittleEndian, kBigEndian));
-
-// Similar tests, but with 64-bit values. Ostensibly this could be
-// shoehorned into the parameterization by using ::testing::Combine,
-// but that would make it difficult to get the types right since these
-// actual test cases aren't parameterized. This could also be written
-// as a type-parameterized test, but combining that with a value-parameterized
-// test seemed really ugly, and also makes it harder to test 64-bit
-// values.
-class ELFSymbolsToModuleTest64 : public ELFSymbolsToModuleTestFixture,
- public TestWithParam<Endianness> {
-public:
- ELFSymbolsToModuleTest64() : ELFSymbolsToModuleTestFixture(GetParam(), 8) {}
-
- void AddElf64Sym(const string& name, uint64_t value,
- uint64_t size, unsigned info, uint16_t shndx) {
- section
- .D32(table.Add(name))
- .D8(info)
- .D8(0) // other
- .D16(shndx)
- .D64(value)
- .D64(size);
- }
-};
-
-TEST_P(ELFSymbolsToModuleTest64, NoFuncs) {
- ProcessSection();
-
- ASSERT_EQ((size_t)0, externs.size());
-}
-
-TEST_P(ELFSymbolsToModuleTest64, OneFunc) {
- const string kFuncName = "superfunc";
- const uint64_t kFuncAddr = 0x1000200030004000ULL;
- const uint64_t kFuncSize = 0x1000;
-
- AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
- ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest64, MultipleFuncs) {
- const string kFuncName1 = "superfunc";
- const uint64_t kFuncAddr1 = 0x1000100010001000ULL;
- const uint64_t kFuncSize1 = 0x1000;
- const string kFuncName2 = "awesomefunc";
- const uint64_t kFuncAddr2 = 0x2000200020002000ULL;
- const uint64_t kFuncSize2 = 0x2f00;
- const string kFuncName3 = "megafunc";
- const uint64_t kFuncAddr3 = 0x3000300030003000ULL;
- const uint64_t kFuncSize3 = 0x3c00;
-
- AddElf64Sym(kFuncName1, kFuncAddr1, kFuncSize1,
- ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
- AddElf64Sym(kFuncName2, kFuncAddr2, kFuncSize2,
- ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 2);
- AddElf64Sym(kFuncName3, kFuncAddr3, kFuncSize3,
- ELF64_ST_INFO(STB_LOCAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 3);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)3, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName1, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr1, extern1->address);
- Module::Extern *extern2 = externs[1];
- EXPECT_EQ(kFuncName2, extern2->name);
- EXPECT_EQ((Module::Address)kFuncAddr2, extern2->address);
- Module::Extern *extern3 = externs[2];
- EXPECT_EQ(kFuncName3, extern3->name);
- EXPECT_EQ((Module::Address)kFuncAddr3, extern3->address);
-}
-
-TEST_P(ELFSymbolsToModuleTest64, SkipStuff) {
- const string kFuncName = "superfunc";
- const uint64_t kFuncAddr = 0x1000100010001000ULL;
- const uint64_t kFuncSize = 0x1000;
-
- // Should skip functions in SHN_UNDEF
- AddElf64Sym("skipme", 0xFFFF, 0x10,
- ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
- SHN_UNDEF);
- AddElf64Sym(kFuncName, kFuncAddr, kFuncSize,
- ELF64_ST_INFO(STB_GLOBAL, STT_FUNC),
- // Doesn't really matter, just can't be SHN_UNDEF.
- SHN_UNDEF + 1);
- // Should skip non-STT_FUNC entries.
- AddElf64Sym("skipmetoo", 0xAAAA, 0x10,
- ELF64_ST_INFO(STB_GLOBAL, STT_FILE),
- SHN_UNDEF + 1);
-
- ProcessSection();
-
- ASSERT_EQ((size_t)1, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_EQ(kFuncName, extern1->name);
- EXPECT_EQ((Module::Address)kFuncAddr, extern1->address);
-}
-
-// Run all the 64-bit tests with both endianness
-INSTANTIATE_TEST_CASE_P(Endian,
- ELFSymbolsToModuleTest64,
- ::testing::Values(kLittleEndian, kBigEndian));
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h
deleted file mode 100644
index e56b37a9f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils-inl.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2012, 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 COMMON_LINUX_ELFUTILS_INL_H__
-#define COMMON_LINUX_ELFUTILS_INL_H__
-
-#include "common/linux/linux_libc_support.h"
-#include "elfutils.h"
-
-namespace google_breakpad {
-
-template<typename ElfClass, typename T>
-const T* GetOffset(const typename ElfClass::Ehdr* elf_header,
- typename ElfClass::Off offset) {
- return reinterpret_cast<const T*>(reinterpret_cast<uintptr_t>(elf_header) +
- offset);
-}
-
-template<typename ElfClass>
-const typename ElfClass::Shdr* FindElfSectionByName(
- const char* name,
- typename ElfClass::Word section_type,
- const typename ElfClass::Shdr* sections,
- const char* section_names,
- const char* names_end,
- int nsection) {
- assert(name != NULL);
- assert(sections != NULL);
- assert(nsection > 0);
-
- int name_len = my_strlen(name);
- if (name_len == 0)
- return NULL;
-
- for (int i = 0; i < nsection; ++i) {
- const char* section_name = section_names + sections[i].sh_name;
- if (sections[i].sh_type == section_type &&
- names_end - section_name >= name_len + 1 &&
- my_strcmp(name, section_name) == 0) {
- return sections + i;
- }
- }
- return NULL;
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_ELFUTILS_INL_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc
deleted file mode 100644
index a79391c13..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/linux/elfutils.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "common/linux/linux_libc_support.h"
-#include "common/linux/elfutils-inl.h"
-
-namespace google_breakpad {
-
-namespace {
-
-template<typename ElfClass>
-void FindElfClassSection(const char *elf_base,
- const char *section_name,
- typename ElfClass::Word section_type,
- const void **section_start,
- size_t *section_size) {
- typedef typename ElfClass::Ehdr Ehdr;
- typedef typename ElfClass::Shdr Shdr;
-
- assert(elf_base);
- assert(section_start);
- assert(section_size);
-
- assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
-
- const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
- assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
-
- const Shdr* sections =
- GetOffset<ElfClass, Shdr>(elf_header, elf_header->e_shoff);
- const Shdr* section_names = sections + elf_header->e_shstrndx;
- const char* names =
- GetOffset<ElfClass, char>(elf_header, section_names->sh_offset);
- const char *names_end = names + section_names->sh_size;
-
- const Shdr* section =
- FindElfSectionByName<ElfClass>(section_name, section_type,
- sections, names, names_end,
- elf_header->e_shnum);
-
- if (section != NULL && section->sh_size > 0) {
- *section_start = elf_base + section->sh_offset;
- *section_size = section->sh_size;
- }
-}
-
-template<typename ElfClass>
-void FindElfClassSegment(const char *elf_base,
- typename ElfClass::Word segment_type,
- const void **segment_start,
- size_t *segment_size) {
- typedef typename ElfClass::Ehdr Ehdr;
- typedef typename ElfClass::Phdr Phdr;
-
- assert(elf_base);
- assert(segment_start);
- assert(segment_size);
-
- assert(my_strncmp(elf_base, ELFMAG, SELFMAG) == 0);
-
- const Ehdr* elf_header = reinterpret_cast<const Ehdr*>(elf_base);
- assert(elf_header->e_ident[EI_CLASS] == ElfClass::kClass);
-
- const Phdr* phdrs =
- GetOffset<ElfClass, Phdr>(elf_header, elf_header->e_phoff);
-
- for (int i = 0; i < elf_header->e_phnum; ++i) {
- if (phdrs[i].p_type == segment_type) {
- *segment_start = elf_base + phdrs[i].p_offset;
- *segment_size = phdrs[i].p_filesz;
- return;
- }
- }
-}
-
-} // namespace
-
-bool IsValidElf(const void* elf_base) {
- return my_strncmp(reinterpret_cast<const char*>(elf_base),
- ELFMAG, SELFMAG) == 0;
-}
-
-int ElfClass(const void* elf_base) {
- const ElfW(Ehdr)* elf_header =
- reinterpret_cast<const ElfW(Ehdr)*>(elf_base);
-
- return elf_header->e_ident[EI_CLASS];
-}
-
-bool FindElfSection(const void *elf_mapped_base,
- const char *section_name,
- uint32_t section_type,
- const void **section_start,
- size_t *section_size,
- int *elfclass) {
- assert(elf_mapped_base);
- assert(section_start);
- assert(section_size);
-
- *section_start = NULL;
- *section_size = 0;
-
- if (!IsValidElf(elf_mapped_base))
- return false;
-
- int cls = ElfClass(elf_mapped_base);
- if (elfclass) {
- *elfclass = cls;
- }
-
- const char* elf_base =
- static_cast<const char*>(elf_mapped_base);
-
- if (cls == ELFCLASS32) {
- FindElfClassSection<ElfClass32>(elf_base, section_name, section_type,
- section_start, section_size);
- return *section_start != NULL;
- } else if (cls == ELFCLASS64) {
- FindElfClassSection<ElfClass64>(elf_base, section_name, section_type,
- section_start, section_size);
- return *section_start != NULL;
- }
-
- return false;
-}
-
-bool FindElfSegment(const void *elf_mapped_base,
- uint32_t segment_type,
- const void **segment_start,
- size_t *segment_size,
- int *elfclass) {
- assert(elf_mapped_base);
- assert(segment_start);
- assert(segment_size);
-
- *segment_start = NULL;
- *segment_size = 0;
-
- if (!IsValidElf(elf_mapped_base))
- return false;
-
- int cls = ElfClass(elf_mapped_base);
- if (elfclass) {
- *elfclass = cls;
- }
-
- const char* elf_base =
- static_cast<const char*>(elf_mapped_base);
-
- if (cls == ELFCLASS32) {
- FindElfClassSegment<ElfClass32>(elf_base, segment_type,
- segment_start, segment_size);
- return *segment_start != NULL;
- } else if (cls == ELFCLASS64) {
- FindElfClassSegment<ElfClass64>(elf_base, segment_type,
- segment_start, segment_size);
- return *segment_start != NULL;
- }
-
- return false;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h b/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h
deleted file mode 100644
index f34ba8314..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/elfutils.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2012, 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.
-//
-// elfutils.h: Utilities for dealing with ELF files.
-//
-
-#ifndef COMMON_LINUX_ELFUTILS_H_
-#define COMMON_LINUX_ELFUTILS_H_
-
-#include <elf.h>
-#include <link.h>
-#include <stdint.h>
-
-namespace google_breakpad {
-
-// Traits classes so consumers can write templatized code to deal
-// with specific ELF bits.
-struct ElfClass32 {
- typedef Elf32_Addr Addr;
- typedef Elf32_Ehdr Ehdr;
- typedef Elf32_Nhdr Nhdr;
- typedef Elf32_Phdr Phdr;
- typedef Elf32_Shdr Shdr;
- typedef Elf32_Half Half;
- typedef Elf32_Off Off;
- typedef Elf32_Sym Sym;
- typedef Elf32_Word Word;
-
- static const int kClass = ELFCLASS32;
- static const uint16_t kMachine = EM_386;
- static const size_t kAddrSize = sizeof(Elf32_Addr);
- static constexpr const char* kMachineName = "x86";
-};
-
-struct ElfClass64 {
- typedef Elf64_Addr Addr;
- typedef Elf64_Ehdr Ehdr;
- typedef Elf64_Nhdr Nhdr;
- typedef Elf64_Phdr Phdr;
- typedef Elf64_Shdr Shdr;
- typedef Elf64_Half Half;
- typedef Elf64_Off Off;
- typedef Elf64_Sym Sym;
- typedef Elf64_Word Word;
-
- static const int kClass = ELFCLASS64;
- static const uint16_t kMachine = EM_X86_64;
- static const size_t kAddrSize = sizeof(Elf64_Addr);
- static constexpr const char* kMachineName = "x86_64";
-};
-
-bool IsValidElf(const void* elf_header);
-int ElfClass(const void* elf_base);
-
-// Attempt to find a section named |section_name| of type |section_type|
-// in the ELF binary data at |elf_mapped_base|. On success, returns true
-// and sets |*section_start| to point to the start of the section data,
-// and |*section_size| to the size of the section's data. If |elfclass|
-// is not NULL, set |*elfclass| to the ELF file class.
-bool FindElfSection(const void *elf_mapped_base,
- const char *section_name,
- uint32_t section_type,
- const void **section_start,
- size_t *section_size,
- int *elfclass);
-
-// Internal helper method, exposed for convenience for callers
-// that already have more info.
-template<typename ElfClass>
-const typename ElfClass::Shdr*
-FindElfSectionByName(const char* name,
- typename ElfClass::Word section_type,
- const typename ElfClass::Shdr* sections,
- const char* section_names,
- const char* names_end,
- int nsection);
-
-// Attempt to find the first segment of type |segment_type| in the ELF
-// binary data at |elf_mapped_base|. On success, returns true and sets
-// |*segment_start| to point to the start of the segment data, and
-// and |*segment_size| to the size of the segment's data. If |elfclass|
-// is not NULL, set |*elfclass| to the ELF file class.
-bool FindElfSegment(const void *elf_mapped_base,
- uint32_t segment_type,
- const void **segment_start,
- size_t *segment_size,
- int *elfclass);
-
-// Convert an offset from an Elf header into a pointer to the mapped
-// address in the current process. Takes an extra template parameter
-// to specify the return type to avoid having to dynamic_cast the
-// result.
-template<typename ElfClass, typename T>
-const T*
-GetOffset(const typename ElfClass::Ehdr* elf_header,
- typename ElfClass::Off offset);
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_ELFUTILS_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
deleted file mode 100644
index 311e03020..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// file_id.cc: Return a unique identifier for a file
-//
-// See file_id.h for documentation
-//
-
-#include "common/linux/file_id.h"
-
-#include <arpa/inet.h>
-#include <assert.h>
-#include <string.h>
-
-#include <algorithm>
-#include <string>
-
-#include "common/linux/elf_gnu_compat.h"
-#include "common/linux/elfutils.h"
-#include "common/linux/linux_libc_support.h"
-#include "common/linux/memory_mapped_file.h"
-#include "common/using_std_string.h"
-#include "third_party/lss/linux_syscall_support.h"
-
-namespace google_breakpad {
-
-// Used in a few places for backwards-compatibility.
-const size_t kMDGUIDSize = sizeof(MDGUID);
-
-FileID::FileID(const char* path) : path_(path) {}
-
-// ELF note name and desc are 32-bits word padded.
-#define NOTE_PADDING(a) ((a + 3) & ~3)
-
-// These functions are also used inside the crashed process, so be safe
-// and use the syscall/libc wrappers instead of direct syscalls or libc.
-
-template<typename ElfClass>
-static bool ElfClassBuildIDNoteIdentifier(const void *section, size_t length,
- wasteful_vector<uint8_t>& identifier) {
- typedef typename ElfClass::Nhdr Nhdr;
-
- const void* section_end = reinterpret_cast<const char*>(section) + length;
- const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
- while (reinterpret_cast<const void *>(note_header) < section_end) {
- if (note_header->n_type == NT_GNU_BUILD_ID)
- break;
- note_header = reinterpret_cast<const Nhdr*>(
- reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
- NOTE_PADDING(note_header->n_namesz) +
- NOTE_PADDING(note_header->n_descsz));
- }
- if (reinterpret_cast<const void *>(note_header) >= section_end ||
- note_header->n_descsz == 0) {
- return false;
- }
-
- const uint8_t* build_id = reinterpret_cast<const uint8_t*>(note_header) +
- sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
- identifier.insert(identifier.end(),
- build_id,
- build_id + note_header->n_descsz);
-
- return true;
-}
-
-// Attempt to locate a .note.gnu.build-id section in an ELF binary
-// and copy it into |identifier|.
-static bool FindElfBuildIDNote(const void* elf_mapped_base,
- wasteful_vector<uint8_t>& identifier) {
- void* note_section;
- size_t note_size;
- int elfclass;
- if ((!FindElfSegment(elf_mapped_base, PT_NOTE,
- (const void**)&note_section, &note_size, &elfclass) ||
- note_size == 0) &&
- (!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
- (const void**)&note_section, &note_size, &elfclass) ||
- note_size == 0)) {
- return false;
- }
-
- if (elfclass == ELFCLASS32) {
- return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size,
- identifier);
- } else if (elfclass == ELFCLASS64) {
- return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size,
- identifier);
- }
-
- return false;
-}
-
-// Attempt to locate the .text section of an ELF binary and generate
-// a simple hash by XORing the first page worth of bytes into |identifier|.
-static bool HashElfTextSection(const void* elf_mapped_base,
- wasteful_vector<uint8_t>& identifier) {
- identifier.resize(kMDGUIDSize);
-
- void* text_section;
- size_t text_size;
- if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
- (const void**)&text_section, &text_size, NULL) ||
- text_size == 0) {
- return false;
- }
-
- // Only provide |kMDGUIDSize| bytes to keep identifiers produced by this
- // function backwards-compatible.
- my_memset(&identifier[0], 0, kMDGUIDSize);
- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
- const uint8_t* ptr_end = ptr + std::min(text_size, static_cast<size_t>(4096));
- while (ptr < ptr_end) {
- for (unsigned i = 0; i < kMDGUIDSize; i++)
- identifier[i] ^= ptr[i];
- ptr += kMDGUIDSize;
- }
- return true;
-}
-
-// static
-bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
- wasteful_vector<uint8_t>& identifier) {
- // Look for a build id note first.
- if (FindElfBuildIDNote(base, identifier))
- return true;
-
- // Fall back on hashing the first page of the text section.
- return HashElfTextSection(base, identifier);
-}
-
-bool FileID::ElfFileIdentifier(wasteful_vector<uint8_t>& identifier) {
- MemoryMappedFile mapped_file(path_.c_str(), 0);
- if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
- return false;
-
- return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
-}
-
-// These three functions are not ever called in an unsafe context, so it's OK
-// to allocate memory and use libc.
-static string bytes_to_hex_string(const uint8_t* bytes, size_t count) {
- string result;
- for (unsigned int idx = 0; idx < count; ++idx) {
- char buf[3];
- snprintf(buf, sizeof(buf), "%02X", bytes[idx]);
- result.append(buf);
- }
- return result;
-}
-
-// static
-string FileID::ConvertIdentifierToUUIDString(
- const wasteful_vector<uint8_t>& identifier) {
- uint8_t identifier_swapped[kMDGUIDSize] = { 0 };
-
- // Endian-ness swap to match dump processor expectation.
- memcpy(identifier_swapped, &identifier[0],
- std::min(kMDGUIDSize, identifier.size()));
- uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
- *data1 = htonl(*data1);
- uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
- *data2 = htons(*data2);
- uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
- *data3 = htons(*data3);
-
- return bytes_to_hex_string(identifier_swapped, kMDGUIDSize);
-}
-
-// static
-string FileID::ConvertIdentifierToString(
- const wasteful_vector<uint8_t>& identifier) {
- return bytes_to_hex_string(&identifier[0], identifier.size());
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h
deleted file mode 100644
index a1d2fd6ed..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// file_id.h: Return a unique identifier for a file
-//
-
-#ifndef COMMON_LINUX_FILE_ID_H__
-#define COMMON_LINUX_FILE_ID_H__
-
-#include <limits.h>
-#include <string>
-
-#include "common/linux/guid_creator.h"
-#include "common/memory.h"
-
-namespace google_breakpad {
-
-// GNU binutils' ld defaults to 'sha1', which is 160 bits == 20 bytes,
-// so this is enough to fit that, which most binaries will use.
-// This is just a sensible default for auto_wasteful_vector so most
-// callers can get away with stack allocation.
-static const size_t kDefaultBuildIdSize = 20;
-
-class FileID {
- public:
- explicit FileID(const char* path);
- ~FileID() {}
-
- // Load the identifier for the elf file path specified in the constructor into
- // |identifier|.
- //
- // The current implementation will look for a .note.gnu.build-id
- // section and use that as the file id, otherwise it falls back to
- // XORing the first 4096 bytes of the .text section to generate an identifier.
- bool ElfFileIdentifier(wasteful_vector<uint8_t>& identifier);
-
- // Load the identifier for the elf file mapped into memory at |base| into
- // |identifier|. Return false if the identifier could not be created for this
- // file.
- static bool ElfFileIdentifierFromMappedFile(
- const void* base,
- wasteful_vector<uint8_t>& identifier);
-
- // Convert the |identifier| data to a string. The string will
- // be formatted as a UUID in all uppercase without dashes.
- // (e.g., 22F065BBFC9C49F780FE26A7CEBD7BCE).
- static std::string ConvertIdentifierToUUIDString(
- const wasteful_vector<uint8_t>& identifier);
-
- // Convert the entire |identifier| data to a hex string.
- static std::string ConvertIdentifierToString(
- const wasteful_vector<uint8_t>& identifier);
-
- private:
- // Storage for the path specified
- std::string path_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_FILE_ID_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc
deleted file mode 100644
index 3a8193034..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/file_id_unittest.cc
+++ /dev/null
@@ -1,338 +0,0 @@
-// 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.
-
-// Unit tests for FileID
-
-#include <elf.h>
-#include <stdlib.h>
-
-#include <string>
-#include <vector>
-
-#include "common/linux/elf_gnu_compat.h"
-#include "common/linux/elfutils.h"
-#include "common/linux/file_id.h"
-#include "common/linux/safe_readlink.h"
-#include "common/linux/synth_elf.h"
-#include "common/test_assembler.h"
-#include "common/tests/auto_tempdir.h"
-#include "common/using_std_string.h"
-#include "breakpad_googletest_includes.h"
-
-using namespace google_breakpad;
-using google_breakpad::synth_elf::ELF;
-using google_breakpad::synth_elf::Notes;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Section;
-using std::vector;
-using ::testing::Types;
-
-namespace {
-
-// Simply calling Section::Append(size, byte) produces a uninteresting pattern
-// that tends to get hashed to 0000...0000. This populates the section with
-// data to produce better hashes.
-void PopulateSection(Section* section, int size, int prime_number) {
- for (int i = 0; i < size; i++)
- section->Append(1, (i % prime_number) % 256);
-}
-
-typedef wasteful_vector<uint8_t> id_vector;
-
-} // namespace
-
-#ifndef __ANDROID__
-// This test is disabled on Android: It will always fail, since there is no
-// 'strip' binary installed on test devices.
-TEST(FileIDStripTest, StripSelf) {
- // Calculate the File ID of this binary using
- // FileID::ElfFileIdentifier, then make a copy of this binary,
- // strip it, and ensure that the result is the same.
- char exe_name[PATH_MAX];
- ASSERT_TRUE(SafeReadLink("/proc/self/exe", exe_name));
-
- // copy our binary to a temp file, and strip it
- AutoTempDir temp_dir;
- string templ = temp_dir.path() + "/file-id-unittest";
- char cmdline[4096];
- sprintf(cmdline, "cp \"%s\" \"%s\"", exe_name, templ.c_str());
- ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
- sprintf(cmdline, "chmod u+w \"%s\"", templ.c_str());
- ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
- sprintf(cmdline, "strip \"%s\"", templ.c_str());
- ASSERT_EQ(0, system(cmdline)) << "Failed to execute: " << cmdline;
-
- PageAllocator allocator;
- id_vector identifier1(&allocator, kDefaultBuildIdSize);
- id_vector identifier2(&allocator, kDefaultBuildIdSize);
-
- FileID fileid1(exe_name);
- EXPECT_TRUE(fileid1.ElfFileIdentifier(identifier1));
- FileID fileid2(templ.c_str());
- EXPECT_TRUE(fileid2.ElfFileIdentifier(identifier2));
-
- string identifier_string1 =
- FileID::ConvertIdentifierToUUIDString(identifier1);
- string identifier_string2 =
- FileID::ConvertIdentifierToUUIDString(identifier2);
- EXPECT_EQ(identifier_string1, identifier_string2);
-}
-#endif // !__ANDROID__
-
-template<typename ElfClass>
-class FileIDTest : public testing::Test {
-public:
- void GetElfContents(ELF& elf) {
- string contents;
- ASSERT_TRUE(elf.GetContents(&contents));
- ASSERT_LT(0U, contents.size());
-
- elfdata_v.clear();
- elfdata_v.insert(elfdata_v.begin(), contents.begin(), contents.end());
- elfdata = &elfdata_v[0];
- }
-
- id_vector make_vector() {
- return id_vector(&allocator, kDefaultBuildIdSize);
- }
-
- template<size_t N>
- string get_file_id(const uint8_t (&data)[N]) {
- id_vector expected_identifier(make_vector());
- expected_identifier.insert(expected_identifier.end(),
- &data[0],
- data + N);
- return FileID::ConvertIdentifierToUUIDString(expected_identifier);
- }
-
- vector<uint8_t> elfdata_v;
- uint8_t* elfdata;
- PageAllocator allocator;
-};
-
-typedef Types<ElfClass32, ElfClass64> ElfClasses;
-
-TYPED_TEST_CASE(FileIDTest, ElfClasses);
-
-TYPED_TEST(FileIDTest, ElfClass) {
- const char expected_identifier_string[] =
- "80808080808000000000008080808080";
- const size_t kTextSectionSize = 128;
-
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- for (size_t i = 0; i < kTextSectionSize; ++i) {
- text.D8(i * 3);
- }
- elf.AddSection(".text", text, SHT_PROGBITS);
- elf.Finish();
- this->GetElfContents(elf);
-
- id_vector identifier(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier));
-
- string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
- EXPECT_EQ(expected_identifier_string, identifier_string);
-}
-
-TYPED_TEST(FileIDTest, BuildID) {
- const uint8_t kExpectedIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13};
- const string expected_identifier_string =
- this->get_file_id(kExpectedIdentifierBytes);
-
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
- Notes notes(kLittleEndian);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
- sizeof(kExpectedIdentifierBytes));
- elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
- elf.Finish();
- this->GetElfContents(elf);
-
- id_vector identifier(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier));
- EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
-
- string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
- EXPECT_EQ(expected_identifier_string, identifier_string);
-}
-
-// Test that a build id note with fewer bytes than usual is handled.
-TYPED_TEST(FileIDTest, BuildIDShort) {
- const uint8_t kExpectedIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03};
- const string expected_identifier_string =
- this->get_file_id(kExpectedIdentifierBytes);
-
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
- Notes notes(kLittleEndian);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
- sizeof(kExpectedIdentifierBytes));
- elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
- elf.Finish();
- this->GetElfContents(elf);
-
- id_vector identifier(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier));
- EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
-
- string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
- EXPECT_EQ(expected_identifier_string, identifier_string);
-}
-
-// Test that a build id note with more bytes than usual is handled.
-TYPED_TEST(FileIDTest, BuildIDLong) {
- const uint8_t kExpectedIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
- const string expected_identifier_string =
- this->get_file_id(kExpectedIdentifierBytes);
-
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
- Notes notes(kLittleEndian);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
- sizeof(kExpectedIdentifierBytes));
- elf.AddSection(".note.gnu.build-id", notes, SHT_NOTE);
- elf.Finish();
- this->GetElfContents(elf);
-
- id_vector identifier(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier));
- EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
-
- string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
- EXPECT_EQ(expected_identifier_string, identifier_string);
-}
-
-TYPED_TEST(FileIDTest, BuildIDPH) {
- const uint8_t kExpectedIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13};
- const string expected_identifier_string =
- this->get_file_id(kExpectedIdentifierBytes);
-
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- text.Append(4096, 0);
- elf.AddSection(".text", text, SHT_PROGBITS);
- Notes notes(kLittleEndian);
- notes.AddNote(0, "Linux",
- reinterpret_cast<const uint8_t *>("\0x42\0x02\0\0"), 4);
- notes.AddNote(NT_GNU_BUILD_ID, "GNU", kExpectedIdentifierBytes,
- sizeof(kExpectedIdentifierBytes));
- int note_idx = elf.AddSection(".note", notes, SHT_NOTE);
- elf.AddSegment(note_idx, note_idx, PT_NOTE);
- elf.Finish();
- this->GetElfContents(elf);
-
- id_vector identifier(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier));
- EXPECT_EQ(sizeof(kExpectedIdentifierBytes), identifier.size());
-
- string identifier_string = FileID::ConvertIdentifierToUUIDString(identifier);
- EXPECT_EQ(expected_identifier_string, identifier_string);
-}
-
-// Test to make sure two files with different text sections produce
-// different hashes when not using a build id.
-TYPED_TEST(FileIDTest, UniqueHashes) {
- {
- ELF elf1(EM_386, TypeParam::kClass, kLittleEndian);
- Section foo_1(kLittleEndian);
- PopulateSection(&foo_1, 32, 5);
- elf1.AddSection(".foo", foo_1, SHT_PROGBITS);
- Section text_1(kLittleEndian);
- PopulateSection(&text_1, 4096, 17);
- elf1.AddSection(".text", text_1, SHT_PROGBITS);
- elf1.Finish();
- this->GetElfContents(elf1);
- }
-
- id_vector identifier_1(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier_1));
- string identifier_string_1 =
- FileID::ConvertIdentifierToUUIDString(identifier_1);
-
- {
- ELF elf2(EM_386, TypeParam::kClass, kLittleEndian);
- Section text_2(kLittleEndian);
- Section foo_2(kLittleEndian);
- PopulateSection(&foo_2, 32, 5);
- elf2.AddSection(".foo", foo_2, SHT_PROGBITS);
- PopulateSection(&text_2, 4096, 31);
- elf2.AddSection(".text", text_2, SHT_PROGBITS);
- elf2.Finish();
- this->GetElfContents(elf2);
- }
-
- id_vector identifier_2(this->make_vector());
- EXPECT_TRUE(FileID::ElfFileIdentifierFromMappedFile(this->elfdata,
- identifier_2));
- string identifier_string_2 =
- FileID::ConvertIdentifierToUUIDString(identifier_2);
-
- EXPECT_NE(identifier_string_1, identifier_string_2);
-}
-
-TYPED_TEST(FileIDTest, ConvertIdentifierToString) {
- const uint8_t kIdentifierBytes[] =
- {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
- const char* kExpected =
- "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
-
- id_vector identifier(this->make_vector());
- identifier.insert(identifier.end(),
- kIdentifierBytes,
- kIdentifierBytes + sizeof(kIdentifierBytes));
- ASSERT_EQ(kExpected,
- FileID::ConvertIdentifierToString(identifier));
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc
deleted file mode 100644
index 6d86fb369..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// 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.
-
-
-#include "common/linux/google_crashdump_uploader.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <iostream>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword) {
- LibcurlWrapper* http_layer = new LibcurlWrapper();
- Init(product,
- version,
- guid,
- ptime,
- ctime,
- email,
- comments,
- minidump_pathname,
- crash_server,
- proxy_host,
- proxy_userpassword,
- http_layer);
-}
-
-GoogleCrashdumpUploader::GoogleCrashdumpUploader(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword,
- LibcurlWrapper* http_layer) {
- Init(product,
- version,
- guid,
- ptime,
- ctime,
- email,
- comments,
- minidump_pathname,
- crash_server,
- proxy_host,
- proxy_userpassword,
- http_layer);
-}
-
-void GoogleCrashdumpUploader::Init(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword,
- LibcurlWrapper* http_layer) {
- product_ = product;
- version_ = version;
- guid_ = guid;
- ptime_ = ptime;
- ctime_ = ctime;
- email_ = email;
- comments_ = comments;
- http_layer_.reset(http_layer);
-
- crash_server_ = crash_server;
- proxy_host_ = proxy_host;
- proxy_userpassword_ = proxy_userpassword;
- minidump_pathname_ = minidump_pathname;
- std::cout << "Uploader initializing";
- std::cout << "\tProduct: " << product_;
- std::cout << "\tVersion: " << version_;
- std::cout << "\tGUID: " << guid_;
- if (!ptime_.empty()) {
- std::cout << "\tProcess uptime: " << ptime_;
- }
- if (!ctime_.empty()) {
- std::cout << "\tCumulative Process uptime: " << ctime_;
- }
- if (!email_.empty()) {
- std::cout << "\tEmail: " << email_;
- }
- if (!comments_.empty()) {
- std::cout << "\tComments: " << comments_;
- }
-}
-
-bool GoogleCrashdumpUploader::CheckRequiredParametersArePresent() {
- string error_text;
- if (product_.empty()) {
- error_text.append("\nProduct name must be specified.");
- }
-
- if (version_.empty()) {
- error_text.append("\nProduct version must be specified.");
- }
-
- if (guid_.empty()) {
- error_text.append("\nClient ID must be specified.");
- }
-
- if (minidump_pathname_.empty()) {
- error_text.append("\nMinidump pathname must be specified.");
- }
-
- if (!error_text.empty()) {
- std::cout << error_text;
- return false;
- }
- return true;
-
-}
-
-bool GoogleCrashdumpUploader::Upload(int* http_status_code,
- string* http_response_header,
- string* http_response_body) {
- bool ok = http_layer_->Init();
- if (!ok) {
- std::cout << "http layer init failed";
- return ok;
- }
-
- if (!CheckRequiredParametersArePresent()) {
- return false;
- }
-
- struct stat st;
- int err = stat(minidump_pathname_.c_str(), &st);
- if (err) {
- std::cout << minidump_pathname_ << " could not be found";
- return false;
- }
-
- parameters_["prod"] = product_;
- parameters_["ver"] = version_;
- parameters_["guid"] = guid_;
- parameters_["ptime"] = ptime_;
- parameters_["ctime"] = ctime_;
- parameters_["email"] = email_;
- parameters_["comments_"] = comments_;
- if (!http_layer_->AddFile(minidump_pathname_,
- "upload_file_minidump")) {
- return false;
- }
- std::cout << "Sending request to " << crash_server_;
- return http_layer_->SendRequest(crash_server_,
- parameters_,
- http_status_code,
- http_response_header,
- http_response_body);
-}
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h
deleted file mode 100644
index a2d0575b5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-
-#ifndef COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
-#define COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
-
-#include <string>
-#include <map>
-
-#include "common/linux/libcurl_wrapper.h"
-#include "common/scoped_ptr.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-class GoogleCrashdumpUploader {
- public:
- GoogleCrashdumpUploader(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword);
-
- GoogleCrashdumpUploader(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword,
- LibcurlWrapper* http_layer);
-
- void Init(const string& product,
- const string& version,
- const string& guid,
- const string& ptime,
- const string& ctime,
- const string& email,
- const string& comments,
- const string& minidump_pathname,
- const string& crash_server,
- const string& proxy_host,
- const string& proxy_userpassword,
- LibcurlWrapper* http_layer);
- bool Upload(int* http_status_code,
- string* http_response_header,
- string* http_response_body);
-
- private:
- bool CheckRequiredParametersArePresent();
-
- scoped_ptr<LibcurlWrapper> http_layer_;
- string product_;
- string version_;
- string guid_;
- string ptime_;
- string ctime_;
- string email_;
- string comments_;
- string minidump_pathname_;
-
- string crash_server_;
- string proxy_host_;
- string proxy_userpassword_;
-
- std::map<string, string> parameters_;
-};
-}
-
-#endif // COMMON_LINUX_GOOGLE_CRASHDUMP_UPLOADER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc
deleted file mode 100644
index e94c5d62a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/google_crashdump_uploader_test.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// 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.
-
-// Unit test for crash dump uploader.
-
-#include <string>
-
-#include "common/linux/google_crashdump_uploader.h"
-#include "breakpad_googletest_includes.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using ::testing::Return;
-using ::testing::_;
-
-class MockLibcurlWrapper : public LibcurlWrapper {
- public:
- MOCK_METHOD0(Init, bool());
- MOCK_METHOD2(SetProxy, bool(const string& proxy_host,
- const string& proxy_userpwd));
- MOCK_METHOD2(AddFile, bool(const string& upload_file_path,
- const string& basename));
- MOCK_METHOD5(SendRequest,
- bool(const string& url,
- const std::map<string, string>& parameters,
- int* http_status_code,
- string* http_header_data,
- string* http_response_data));
-};
-
-class GoogleCrashdumpUploaderTest : public ::testing::Test {
-};
-
-TEST_F(GoogleCrashdumpUploaderTest, InitFailsCausesUploadFailure) {
- MockLibcurlWrapper m;
- EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(false));
- GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
- "1.0",
- "AAA-BBB",
- "",
- "",
- "test@test.com",
- "none",
- "/tmp/foo.dmp",
- "http://foo.com",
- "",
- "",
- &m);
- ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL));
-}
-
-TEST_F(GoogleCrashdumpUploaderTest, TestSendRequestHappensWithValidParameters) {
- // Create a temp file
- char tempfn[80] = "/tmp/googletest-upload-XXXXXX";
- int fd = mkstemp(tempfn);
- ASSERT_NE(fd, -1);
- close(fd);
-
- MockLibcurlWrapper m;
- EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(m, AddFile(tempfn, _)).WillOnce(Return(true));
- EXPECT_CALL(m,
- SendRequest("http://foo.com",_,_,_,_)).Times(1).WillOnce(Return(true));
- GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
- "1.0",
- "AAA-BBB",
- "",
- "",
- "test@test.com",
- "none",
- tempfn,
- "http://foo.com",
- "",
- "",
- &m);
- ASSERT_TRUE(uploader->Upload(NULL, NULL, NULL));
-}
-
-
-TEST_F(GoogleCrashdumpUploaderTest, InvalidPathname) {
- MockLibcurlWrapper m;
- EXPECT_CALL(m, Init()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(m, SendRequest(_,_,_,_,_)).Times(0);
- GoogleCrashdumpUploader *uploader = new GoogleCrashdumpUploader("foobar",
- "1.0",
- "AAA-BBB",
- "",
- "",
- "test@test.com",
- "none",
- "/tmp/foo.dmp",
- "http://foo.com",
- "",
- "",
- &m);
- ASSERT_FALSE(uploader->Upload(NULL, NULL, NULL));
-}
-
-TEST_F(GoogleCrashdumpUploaderTest, TestRequiredParametersMustBePresent) {
- // Test with empty product name.
- GoogleCrashdumpUploader uploader("",
- "1.0",
- "AAA-BBB",
- "",
- "",
- "test@test.com",
- "none",
- "/tmp/foo.dmp",
- "http://foo.com",
- "",
- "");
- ASSERT_FALSE(uploader.Upload(NULL, NULL, NULL));
-
- // Test with empty product version.
- GoogleCrashdumpUploader uploader1("product",
- "",
- "AAA-BBB",
- "",
- "",
- "",
- "",
- "/tmp/foo.dmp",
- "",
- "",
- "");
-
- ASSERT_FALSE(uploader1.Upload(NULL, NULL, NULL));
-
- // Test with empty client GUID.
- GoogleCrashdumpUploader uploader2("product",
- "1.0",
- "",
- "",
- "",
- "",
- "",
- "/tmp/foo.dmp",
- "",
- "",
- "");
- ASSERT_FALSE(uploader2.Upload(NULL, NULL, NULL));
-}
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc
deleted file mode 100644
index bfb308ee2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/linux/guid_creator.h"
-
-#include <assert.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <unistd.h>
-
-//
-// GUIDGenerator
-//
-// This class is used to generate random GUID.
-// Currently use random number to generate a GUID since Linux has
-// no native GUID generator. This should be OK since we don't expect
-// crash to happen very offen.
-//
-class GUIDGenerator {
- public:
- static uint32_t BytesToUInt32(const uint8_t bytes[]) {
- return ((uint32_t) bytes[0]
- | ((uint32_t) bytes[1] << 8)
- | ((uint32_t) bytes[2] << 16)
- | ((uint32_t) bytes[3] << 24));
- }
-
- static void UInt32ToBytes(uint8_t bytes[], uint32_t n) {
- bytes[0] = n & 0xff;
- bytes[1] = (n >> 8) & 0xff;
- bytes[2] = (n >> 16) & 0xff;
- bytes[3] = (n >> 24) & 0xff;
- }
-
- static bool CreateGUID(GUID *guid) {
- InitOnce();
- guid->data1 = random();
- guid->data2 = (uint16_t)(random());
- guid->data3 = (uint16_t)(random());
- UInt32ToBytes(&guid->data4[0], random());
- UInt32ToBytes(&guid->data4[4], random());
- return true;
- }
-
- private:
- static void InitOnce() {
- pthread_once(&once_control, &InitOnceImpl);
- }
-
- static void InitOnceImpl() {
- srandom(time(NULL));
- }
-
- static pthread_once_t once_control;
-};
-
-pthread_once_t GUIDGenerator::once_control = PTHREAD_ONCE_INIT;
-
-bool CreateGUID(GUID *guid) {
- return GUIDGenerator::CreateGUID(guid);
-}
-
-// Parse guid to string.
-bool GUIDToString(const GUID *guid, char *buf, int buf_len) {
- // Should allow more space the the max length of GUID.
- assert(buf_len > kGUIDStringLength);
- int num = snprintf(buf, buf_len, kGUIDFormatString,
- guid->data1, guid->data2, guid->data3,
- GUIDGenerator::BytesToUInt32(&(guid->data4[0])),
- GUIDGenerator::BytesToUInt32(&(guid->data4[4])));
- if (num != kGUIDStringLength)
- return false;
-
- buf[num] = '\0';
- return true;
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h b/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h
deleted file mode 100644
index c86d856c4..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/guid_creator.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef COMMON_LINUX_GUID_CREATOR_H__
-#define COMMON_LINUX_GUID_CREATOR_H__
-
-#include "google_breakpad/common/minidump_format.h"
-
-typedef MDGUID GUID;
-
-// Format string for parsing GUID.
-#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x"
-// Length of GUID string. Don't count the ending '\0'.
-#define kGUIDStringLength 36
-
-// Create a guid.
-bool CreateGUID(GUID *guid);
-
-// Get the string from guid.
-bool GUIDToString(const GUID *guid, char *buf, int buf_len);
-
-#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc
deleted file mode 100644
index 702526af7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.cc
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/linux/http_upload.h"
-
-#include <assert.h>
-#include <dlfcn.h>
-#include "third_party/curl/curl.h"
-
-namespace {
-
-// Callback to get the response data from server.
-static size_t WriteCallback(void *ptr, size_t size,
- size_t nmemb, void *userp) {
- if (!userp)
- return 0;
-
- string *response = reinterpret_cast<string *>(userp);
- size_t real_size = size * nmemb;
- response->append(reinterpret_cast<char *>(ptr), real_size);
- return real_size;
-}
-
-} // namespace
-
-namespace google_breakpad {
-
-static const char kUserAgent[] = "Breakpad/1.0 (Linux)";
-
-// static
-bool HTTPUpload::SendRequest(const string &url,
- const map<string, string> &parameters,
- const map<string, string> &files,
- const string &proxy,
- const string &proxy_user_pwd,
- const string &ca_certificate_file,
- string *response_body,
- long *response_code,
- string *error_description) {
- if (response_code != NULL)
- *response_code = 0;
-
- if (!CheckParameters(parameters))
- return false;
-
- // We may have been linked statically; if curl_easy_init is in the
- // current binary, no need to search for a dynamic version.
- void* curl_lib = dlopen(NULL, RTLD_NOW);
- if (!CheckCurlLib(curl_lib)) {
- fprintf(stderr,
- "Failed to open curl lib from binary, use libcurl.so instead\n");
- dlerror(); // Clear dlerror before attempting to open libraries.
- dlclose(curl_lib);
- curl_lib = NULL;
- }
- if (!curl_lib) {
- curl_lib = dlopen("libcurl.so", RTLD_NOW);
- }
- if (!curl_lib) {
- if (error_description != NULL)
- *error_description = dlerror();
- curl_lib = dlopen("libcurl.so.4", RTLD_NOW);
- }
- if (!curl_lib) {
- // Debian gives libcurl a different name when it is built against GnuTLS
- // instead of OpenSSL.
- curl_lib = dlopen("libcurl-gnutls.so.4", RTLD_NOW);
- }
- if (!curl_lib) {
- curl_lib = dlopen("libcurl.so.3", RTLD_NOW);
- }
- if (!curl_lib) {
- return false;
- }
-
- CURL* (*curl_easy_init)(void);
- *(void**) (&curl_easy_init) = dlsym(curl_lib, "curl_easy_init");
- CURL *curl = (*curl_easy_init)();
- if (error_description != NULL)
- *error_description = "No Error";
-
- if (!curl) {
- dlclose(curl_lib);
- return false;
- }
-
- CURLcode err_code = CURLE_OK;
- CURLcode (*curl_easy_setopt)(CURL *, CURLoption, ...);
- *(void**) (&curl_easy_setopt) = dlsym(curl_lib, "curl_easy_setopt");
- (*curl_easy_setopt)(curl, CURLOPT_URL, url.c_str());
- (*curl_easy_setopt)(curl, CURLOPT_USERAGENT, kUserAgent);
- // Support multithread by disabling timeout handling, would get SIGSEGV with
- // Curl_resolv_timeout in stack trace otherwise.
- // See https://curl.haxx.se/libcurl/c/threadsafe.html
- (*curl_easy_setopt)(curl, CURLOPT_NOSIGNAL, 1);
- // Set proxy information if necessary.
- if (!proxy.empty())
- (*curl_easy_setopt)(curl, CURLOPT_PROXY, proxy.c_str());
- if (!proxy_user_pwd.empty())
- (*curl_easy_setopt)(curl, CURLOPT_PROXYUSERPWD, proxy_user_pwd.c_str());
-
- if (!ca_certificate_file.empty())
- (*curl_easy_setopt)(curl, CURLOPT_CAINFO, ca_certificate_file.c_str());
-
- struct curl_httppost *formpost = NULL;
- struct curl_httppost *lastptr = NULL;
- // Add form data.
- CURLFORMcode (*curl_formadd)(struct curl_httppost **, struct curl_httppost **, ...);
- *(void**) (&curl_formadd) = dlsym(curl_lib, "curl_formadd");
- map<string, string>::const_iterator iter = parameters.begin();
- for (; iter != parameters.end(); ++iter)
- (*curl_formadd)(&formpost, &lastptr,
- CURLFORM_COPYNAME, iter->first.c_str(),
- CURLFORM_COPYCONTENTS, iter->second.c_str(),
- CURLFORM_END);
-
- // Add form files.
- for (iter = files.begin(); iter != files.end(); ++iter) {
- (*curl_formadd)(&formpost, &lastptr,
- CURLFORM_COPYNAME, iter->first.c_str(),
- CURLFORM_FILE, iter->second.c_str(),
- CURLFORM_END);
- }
-
- (*curl_easy_setopt)(curl, CURLOPT_HTTPPOST, formpost);
-
- // Disable 100-continue header.
- struct curl_slist *headerlist = NULL;
- char buf[] = "Expect:";
- struct curl_slist* (*curl_slist_append)(struct curl_slist *, const char *);
- *(void**) (&curl_slist_append) = dlsym(curl_lib, "curl_slist_append");
- headerlist = (*curl_slist_append)(headerlist, buf);
- (*curl_easy_setopt)(curl, CURLOPT_HTTPHEADER, headerlist);
-
- if (response_body != NULL) {
- (*curl_easy_setopt)(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
- (*curl_easy_setopt)(curl, CURLOPT_WRITEDATA,
- reinterpret_cast<void *>(response_body));
- }
-
- // Fail if 400+ is returned from the web server.
- (*curl_easy_setopt)(curl, CURLOPT_FAILONERROR, 1);
-
- CURLcode (*curl_easy_perform)(CURL *);
- *(void**) (&curl_easy_perform) = dlsym(curl_lib, "curl_easy_perform");
- err_code = (*curl_easy_perform)(curl);
- if (response_code != NULL) {
- CURLcode (*curl_easy_getinfo)(CURL *, CURLINFO, ...);
- *(void**) (&curl_easy_getinfo) = dlsym(curl_lib, "curl_easy_getinfo");
- (*curl_easy_getinfo)(curl, CURLINFO_RESPONSE_CODE, response_code);
- }
- const char* (*curl_easy_strerror)(CURLcode);
- *(void**) (&curl_easy_strerror) = dlsym(curl_lib, "curl_easy_strerror");
-#ifndef NDEBUG
- if (err_code != CURLE_OK)
- fprintf(stderr, "Failed to send http request to %s, error: %s\n",
- url.c_str(),
- (*curl_easy_strerror)(err_code));
-#endif
- if (error_description != NULL)
- *error_description = (*curl_easy_strerror)(err_code);
-
- void (*curl_easy_cleanup)(CURL *);
- *(void**) (&curl_easy_cleanup) = dlsym(curl_lib, "curl_easy_cleanup");
- (*curl_easy_cleanup)(curl);
- if (formpost != NULL) {
- void (*curl_formfree)(struct curl_httppost *);
- *(void**) (&curl_formfree) = dlsym(curl_lib, "curl_formfree");
- (*curl_formfree)(formpost);
- }
- if (headerlist != NULL) {
- void (*curl_slist_free_all)(struct curl_slist *);
- *(void**) (&curl_slist_free_all) = dlsym(curl_lib, "curl_slist_free_all");
- (*curl_slist_free_all)(headerlist);
- }
- dlclose(curl_lib);
- return err_code == CURLE_OK;
-}
-
-// static
-bool HTTPUpload::CheckCurlLib(void* curl_lib) {
- return curl_lib &&
- dlsym(curl_lib, "curl_easy_init") &&
- dlsym(curl_lib, "curl_easy_setopt");
-}
-
-// static
-bool HTTPUpload::CheckParameters(const map<string, string> &parameters) {
- for (map<string, string>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const string &str = pos->first;
- if (str.size() == 0)
- return false; // disallow empty parameter names
- for (unsigned int i = 0; i < str.size(); ++i) {
- int c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h b/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h
deleted file mode 100644
index bc1d5d570..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/http_upload.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
-// request using libcurl. It currently supports requests that contain
-// a set of string parameters (key/value pairs), and a file to upload.
-
-#ifndef COMMON_LINUX_HTTP_UPLOAD_H__
-#define COMMON_LINUX_HTTP_UPLOAD_H__
-
-#include <map>
-#include <string>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using std::map;
-
-class HTTPUpload {
- public:
- // Sends the given sets of parameters and files as a multipart POST
- // request to the given URL.
- // Each key in |files| is the name of the file part of the request
- // (i.e. it corresponds to the name= attribute on an <input type="file">.
- // Parameter names must contain only printable ASCII characters,
- // and may not contain a quote (") character.
- // Only HTTP(S) URLs are currently supported. Returns true on success.
- // If the request is successful and response_body is non-NULL,
- // the response body will be returned in response_body.
- // If response_code is non-NULL, it will be set to the HTTP response code
- // received (or 0 if the request failed before getting an HTTP response).
- // If the send fails, a description of the error will be
- // returned in error_description.
- static bool SendRequest(const string &url,
- const map<string, string> &parameters,
- const map<string, string> &files,
- const string &proxy,
- const string &proxy_user_pwd,
- const string &ca_certificate_file,
- string *response_body,
- long *response_code,
- string *error_description);
-
- private:
- // Checks that the given list of parameters has only printable
- // ASCII characters in the parameter name, and does not contain
- // any quote (") characters. Returns true if so.
- static bool CheckParameters(const map<string, string> &parameters);
-
- // Checks the curl_lib parameter points to a valid curl lib.
- static bool CheckCurlLib(void* curl_lib);
-
- // No instances of this class should be created.
- // Disallow all constructors, destructors, and operator=.
- HTTPUpload();
- explicit HTTPUpload(const HTTPUpload &);
- void operator=(const HTTPUpload &);
- ~HTTPUpload();
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_HTTP_UPLOAD_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h b/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h
deleted file mode 100644
index efd274c20..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/ignore_ret.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 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 COMMON_LINUX_IGNORE_RET_H_
-#define COMMON_LINUX_IGNORE_RET_H_
-
-// Some compilers are prone to warn about unused return values. In cases where
-// either a) the call cannot fail, or b) there is nothing that can be done when
-// the call fails, IGNORE_RET() can be used to mark the return code as ignored.
-// This avoids spurious compiler warnings.
-
-#define IGNORE_RET(x) do { if (x) {} } while (0)
-
-#endif // COMMON_LINUX_IGNORE_RET_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc
deleted file mode 100644
index fd4e34cd8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// 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.
-
-#include <dlfcn.h>
-
-#include <iostream>
-#include <string>
-
-#include "common/linux/libcurl_wrapper.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-LibcurlWrapper::LibcurlWrapper()
- : init_ok_(false),
- formpost_(NULL),
- lastptr_(NULL),
- headerlist_(NULL) {
- curl_lib_ = dlopen("libcurl.so", RTLD_NOW);
- if (!curl_lib_) {
- curl_lib_ = dlopen("libcurl.so.4", RTLD_NOW);
- }
- if (!curl_lib_) {
- curl_lib_ = dlopen("libcurl.so.3", RTLD_NOW);
- }
- if (!curl_lib_) {
- std::cout << "Could not find libcurl via dlopen";
- return;
- }
- std::cout << "LibcurlWrapper init succeeded";
- init_ok_ = true;
- return;
-}
-
-LibcurlWrapper::~LibcurlWrapper() {}
-
-bool LibcurlWrapper::SetProxy(const string& proxy_host,
- const string& proxy_userpwd) {
- if (!init_ok_) {
- return false;
- }
- // Set proxy information if necessary.
- if (!proxy_host.empty()) {
- (*easy_setopt_)(curl_, CURLOPT_PROXY, proxy_host.c_str());
- } else {
- std::cout << "SetProxy called with empty proxy host.";
- return false;
- }
- if (!proxy_userpwd.empty()) {
- (*easy_setopt_)(curl_, CURLOPT_PROXYUSERPWD, proxy_userpwd.c_str());
- } else {
- std::cout << "SetProxy called with empty proxy username/password.";
- return false;
- }
- std::cout << "Set proxy host to " << proxy_host;
- return true;
-}
-
-bool LibcurlWrapper::AddFile(const string& upload_file_path,
- const string& basename) {
- if (!init_ok_) {
- return false;
- }
- std::cout << "Adding " << upload_file_path << " to form upload.";
- // Add form file.
- (*formadd_)(&formpost_, &lastptr_,
- CURLFORM_COPYNAME, basename.c_str(),
- CURLFORM_FILE, upload_file_path.c_str(),
- CURLFORM_END);
-
- return true;
-}
-
-// Callback to get the response data from server.
-static size_t WriteCallback(void *ptr, size_t size,
- size_t nmemb, void *userp) {
- if (!userp)
- return 0;
-
- string *response = reinterpret_cast<string *>(userp);
- size_t real_size = size * nmemb;
- response->append(reinterpret_cast<char *>(ptr), real_size);
- return real_size;
-}
-
-bool LibcurlWrapper::SendRequest(const string& url,
- const std::map<string, string>& parameters,
- int* http_status_code,
- string* http_header_data,
- string* http_response_data) {
- (*easy_setopt_)(curl_, CURLOPT_URL, url.c_str());
- std::map<string, string>::const_iterator iter = parameters.begin();
- for (; iter != parameters.end(); ++iter)
- (*formadd_)(&formpost_, &lastptr_,
- CURLFORM_COPYNAME, iter->first.c_str(),
- CURLFORM_COPYCONTENTS, iter->second.c_str(),
- CURLFORM_END);
-
- (*easy_setopt_)(curl_, CURLOPT_HTTPPOST, formpost_);
- if (http_response_data != NULL) {
- http_response_data->clear();
- (*easy_setopt_)(curl_, CURLOPT_WRITEFUNCTION, WriteCallback);
- (*easy_setopt_)(curl_, CURLOPT_WRITEDATA,
- reinterpret_cast<void *>(http_response_data));
- }
- if (http_header_data != NULL) {
- http_header_data->clear();
- (*easy_setopt_)(curl_, CURLOPT_HEADERFUNCTION, WriteCallback);
- (*easy_setopt_)(curl_, CURLOPT_HEADERDATA,
- reinterpret_cast<void *>(http_header_data));
- }
-
- CURLcode err_code = CURLE_OK;
- err_code = (*easy_perform_)(curl_);
- easy_strerror_ = reinterpret_cast<const char* (*)(CURLcode)>
- (dlsym(curl_lib_, "curl_easy_strerror"));
-
- if (http_status_code != NULL) {
- (*easy_getinfo_)(curl_, CURLINFO_RESPONSE_CODE, http_status_code);
- }
-
-#ifndef NDEBUG
- if (err_code != CURLE_OK)
- fprintf(stderr, "Failed to send http request to %s, error: %s\n",
- url.c_str(),
- (*easy_strerror_)(err_code));
-#endif
- if (headerlist_ != NULL) {
- (*slist_free_all_)(headerlist_);
- }
-
- (*easy_cleanup_)(curl_);
- if (formpost_ != NULL) {
- (*formfree_)(formpost_);
- }
-
- return err_code == CURLE_OK;
-}
-
-bool LibcurlWrapper::Init() {
- if (!init_ok_) {
- std::cout << "Init_OK was not true in LibcurlWrapper::Init(), check earlier log messages";
- return false;
- }
-
- if (!SetFunctionPointers()) {
- std::cout << "Could not find function pointers";
- init_ok_ = false;
- return false;
- }
-
- curl_ = (*easy_init_)();
-
- last_curl_error_ = "No Error";
-
- if (!curl_) {
- dlclose(curl_lib_);
- std::cout << "Curl initialization failed";
- return false;
- }
-
- // Disable 100-continue header.
- char buf[] = "Expect:";
-
- headerlist_ = (*slist_append_)(headerlist_, buf);
- (*easy_setopt_)(curl_, CURLOPT_HTTPHEADER, headerlist_);
- return true;
-}
-
-#define SET_AND_CHECK_FUNCTION_POINTER(var, function_name, type) \
- var = reinterpret_cast<type>(dlsym(curl_lib_, function_name)); \
- if (!var) { \
- std::cout << "Could not find libcurl function " << function_name; \
- init_ok_ = false; \
- return false; \
- }
-
-bool LibcurlWrapper::SetFunctionPointers() {
-
- SET_AND_CHECK_FUNCTION_POINTER(easy_init_,
- "curl_easy_init",
- CURL*(*)());
-
- SET_AND_CHECK_FUNCTION_POINTER(easy_setopt_,
- "curl_easy_setopt",
- CURLcode(*)(CURL*, CURLoption, ...));
-
- SET_AND_CHECK_FUNCTION_POINTER(formadd_, "curl_formadd",
- CURLFORMcode(*)(curl_httppost**, curl_httppost**, ...));
-
- SET_AND_CHECK_FUNCTION_POINTER(slist_append_, "curl_slist_append",
- curl_slist*(*)(curl_slist*, const char*));
-
- SET_AND_CHECK_FUNCTION_POINTER(easy_perform_,
- "curl_easy_perform",
- CURLcode(*)(CURL*));
-
- SET_AND_CHECK_FUNCTION_POINTER(easy_cleanup_,
- "curl_easy_cleanup",
- void(*)(CURL*));
-
- SET_AND_CHECK_FUNCTION_POINTER(easy_getinfo_,
- "curl_easy_getinfo",
- CURLcode(*)(CURL *, CURLINFO info, ...));
-
- SET_AND_CHECK_FUNCTION_POINTER(slist_free_all_,
- "curl_slist_free_all",
- void(*)(curl_slist*));
-
- SET_AND_CHECK_FUNCTION_POINTER(formfree_,
- "curl_formfree",
- void(*)(curl_httppost*));
- return true;
-}
-
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h
deleted file mode 100644
index 25905ad8f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/libcurl_wrapper.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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.
-
-// A wrapper for libcurl to do HTTP Uploads, to support easy mocking
-// and unit testing of the HTTPUpload class.
-
-#ifndef COMMON_LINUX_LIBCURL_WRAPPER_H_
-#define COMMON_LINUX_LIBCURL_WRAPPER_H_
-
-#include <string>
-#include <map>
-
-#include "common/using_std_string.h"
-#include "third_party/curl/curl.h"
-
-namespace google_breakpad {
-class LibcurlWrapper {
- public:
- LibcurlWrapper();
- virtual ~LibcurlWrapper();
- virtual bool Init();
- virtual bool SetProxy(const string& proxy_host,
- const string& proxy_userpwd);
- virtual bool AddFile(const string& upload_file_path,
- const string& basename);
- virtual bool SendRequest(const string& url,
- const std::map<string, string>& parameters,
- int* http_status_code,
- string* http_header_data,
- string* http_response_data);
- private:
- // This function initializes class state corresponding to function
- // pointers into the CURL library.
- bool SetFunctionPointers();
-
- bool init_ok_; // Whether init succeeded
- void* curl_lib_; // Pointer to result of dlopen() on
- // curl library
- string last_curl_error_; // The text of the last error when
- // dealing
- // with CURL.
-
- CURL *curl_; // Pointer for handle for CURL calls.
-
- CURL* (*easy_init_)(void);
-
- // Stateful pointers for calling into curl_formadd()
- struct curl_httppost *formpost_;
- struct curl_httppost *lastptr_;
- struct curl_slist *headerlist_;
-
- // Function pointers into CURL library
- CURLcode (*easy_setopt_)(CURL *, CURLoption, ...);
- CURLFORMcode (*formadd_)(struct curl_httppost **,
- struct curl_httppost **, ...);
- struct curl_slist* (*slist_append_)(struct curl_slist *, const char *);
- void (*slist_free_all_)(struct curl_slist *);
- CURLcode (*easy_perform_)(CURL *);
- const char* (*easy_strerror_)(CURLcode);
- void (*easy_cleanup_)(CURL *);
- CURLcode (*easy_getinfo_)(CURL *, CURLINFO info, ...);
- void (*formfree_)(struct curl_httppost *);
-
-};
-}
-
-#endif // COMMON_LINUX_LIBCURL_WRAPPER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc
deleted file mode 100644
index 08b0325e6..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This source file provides replacements for libc functions that we need. If
-// we call the libc functions directly we risk crashing in the dynamic linker
-// as it tries to resolve uncached PLT entries.
-
-#include "common/linux/linux_libc_support.h"
-
-#include <stddef.h>
-
-extern "C" {
-
-size_t my_strlen(const char* s) {
- size_t len = 0;
- while (*s++) len++;
- return len;
-}
-
-int my_strcmp(const char* a, const char* b) {
- for (;;) {
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- else if (*a == 0)
- return 0;
- a++;
- b++;
- }
-}
-
-int my_strncmp(const char* a, const char* b, size_t len) {
- for (size_t i = 0; i < len; ++i) {
- if (*a < *b)
- return -1;
- else if (*a > *b)
- return 1;
- else if (*a == 0)
- return 0;
- a++;
- b++;
- }
-
- return 0;
-}
-
-// Parse a non-negative integer.
-// result: (output) the resulting non-negative integer
-// s: a NUL terminated string
-// Return true iff successful.
-bool my_strtoui(int* result, const char* s) {
- if (*s == 0)
- return false;
- int r = 0;
- for (;; s++) {
- if (*s == 0)
- break;
- const int old_r = r;
- r *= 10;
- if (*s < '0' || *s > '9')
- return false;
- r += *s - '0';
- if (r < old_r)
- return false;
- }
-
- *result = r;
- return true;
-}
-
-// Return the length of the given unsigned integer when expressed in base 10.
-unsigned my_uint_len(uintmax_t i) {
- if (!i)
- return 1;
-
- int len = 0;
- while (i) {
- len++;
- i /= 10;
- }
-
- return len;
-}
-
-// Convert an unsigned integer to a string
-// output: (output) the resulting string is written here. This buffer must be
-// large enough to hold the resulting string. Call |my_uint_len| to get the
-// required length.
-// i: the unsigned integer to serialise.
-// i_len: the length of the integer in base 10 (see |my_uint_len|).
-void my_uitos(char* output, uintmax_t i, unsigned i_len) {
- for (unsigned index = i_len; index; --index, i /= 10)
- output[index - 1] = '0' + (i % 10);
-}
-
-const char* my_strchr(const char* haystack, char needle) {
- while (*haystack && *haystack != needle)
- haystack++;
- if (*haystack == needle)
- return haystack;
- return (const char*) 0;
-}
-
-const char* my_strrchr(const char* haystack, char needle) {
- const char* ret = NULL;
- while (*haystack) {
- if (*haystack == needle)
- ret = haystack;
- haystack++;
- }
- return ret;
-}
-
-void* my_memchr(const void* src, int needle, size_t src_len) {
- const unsigned char* p = (const unsigned char*)src;
- const unsigned char* p_end = p + src_len;
- for (; p < p_end; ++p) {
- if (*p == needle)
- return (void*)p;
- }
- return NULL;
-}
-
-// Read a hex value
-// result: (output) the resulting value
-// s: a string
-// Returns a pointer to the first invalid charactor.
-const char* my_read_hex_ptr(uintptr_t* result, const char* s) {
- uintptr_t r = 0;
-
- for (;; ++s) {
- if (*s >= '0' && *s <= '9') {
- r <<= 4;
- r += *s - '0';
- } else if (*s >= 'a' && *s <= 'f') {
- r <<= 4;
- r += (*s - 'a') + 10;
- } else if (*s >= 'A' && *s <= 'F') {
- r <<= 4;
- r += (*s - 'A') + 10;
- } else {
- break;
- }
- }
-
- *result = r;
- return s;
-}
-
-const char* my_read_decimal_ptr(uintptr_t* result, const char* s) {
- uintptr_t r = 0;
-
- for (;; ++s) {
- if (*s >= '0' && *s <= '9') {
- r *= 10;
- r += *s - '0';
- } else {
- break;
- }
- }
- *result = r;
- return s;
-}
-
-void my_memset(void* ip, char c, size_t len) {
- char* p = (char *) ip;
- while (len--)
- *p++ = c;
-}
-
-size_t my_strlcpy(char* s1, const char* s2, size_t len) {
- size_t pos1 = 0;
- size_t pos2 = 0;
-
- while (s2[pos2] != '\0') {
- if (pos1 + 1 < len) {
- s1[pos1] = s2[pos2];
- pos1++;
- }
- pos2++;
- }
- if (len > 0)
- s1[pos1] = '\0';
-
- return pos2;
-}
-
-size_t my_strlcat(char* s1, const char* s2, size_t len) {
- size_t pos1 = 0;
-
- while (pos1 < len && s1[pos1] != '\0')
- pos1++;
-
- if (pos1 == len)
- return pos1;
-
- return pos1 + my_strlcpy(s1 + pos1, s2, len - pos1);
-}
-
-int my_isspace(int ch) {
- // Matches the C locale.
- const char spaces[] = " \t\f\n\r\t\v";
- for (size_t i = 0; i < sizeof(spaces); i++) {
- if (ch == spaces[i])
- return 1;
- }
- return 0;
-}
-
-} // extern "C"
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h
deleted file mode 100644
index ec5a8d6b6..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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.
-
-// This header provides replacements for libc functions that we need. We if
-// call the libc functions directly we risk crashing in the dynamic linker as
-// it tries to resolve uncached PLT entries.
-
-#ifndef CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
-#define CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
-
-#include <stdint.h>
-#include <limits.h>
-#include <sys/types.h>
-
-extern "C" {
-
-extern size_t my_strlen(const char* s);
-
-extern int my_strcmp(const char* a, const char* b);
-
-extern int my_strncmp(const char* a, const char* b, size_t len);
-
-// Parse a non-negative integer.
-// result: (output) the resulting non-negative integer
-// s: a NUL terminated string
-// Return true iff successful.
-extern bool my_strtoui(int* result, const char* s);
-
-// Return the length of the given unsigned integer when expressed in base 10.
-extern unsigned my_uint_len(uintmax_t i);
-
-// Convert an unsigned integer to a string
-// output: (output) the resulting string is written here. This buffer must be
-// large enough to hold the resulting string. Call |my_uint_len| to get the
-// required length.
-// i: the unsigned integer to serialise.
-// i_len: the length of the integer in base 10 (see |my_uint_len|).
-extern void my_uitos(char* output, uintmax_t i, unsigned i_len);
-
-extern const char* my_strchr(const char* haystack, char needle);
-
-extern const char* my_strrchr(const char* haystack, char needle);
-
-// Read a hex value
-// result: (output) the resulting value
-// s: a string
-// Returns a pointer to the first invalid charactor.
-extern const char* my_read_hex_ptr(uintptr_t* result, const char* s);
-
-extern const char* my_read_decimal_ptr(uintptr_t* result, const char* s);
-
-extern void my_memset(void* ip, char c, size_t len);
-
-extern void* my_memchr(const void* src, int c, size_t len);
-
-// The following are considered safe to use in a compromised environment.
-// Besides, this gives the compiler an opportunity to optimize their calls.
-#define my_memcpy memcpy
-#define my_memmove memmove
-#define my_memcmp memcmp
-
-extern size_t my_strlcpy(char* s1, const char* s2, size_t len);
-
-extern size_t my_strlcat(char* s1, const char* s2, size_t len);
-
-extern int my_isspace(int ch);
-
-} // extern "C"
-
-#endif // CLIENT_LINUX_LINUX_LIBC_SUPPORT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc
deleted file mode 100644
index adadfed44..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support_unittest.cc
+++ /dev/null
@@ -1,213 +0,0 @@
-// 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.
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/linux_libc_support.h"
-
-namespace {
-typedef testing::Test LinuxLibcSupportTest;
-}
-
-TEST(LinuxLibcSupportTest, strlen) {
- static const char* test_data[] = { "", "a", "aa", "aaa", "aabc", NULL };
- for (unsigned i = 0; ; ++i) {
- if (!test_data[i])
- break;
- ASSERT_EQ(strlen(test_data[i]), my_strlen(test_data[i]));
- }
-}
-
-TEST(LinuxLibcSupportTest, strcmp) {
- static const char* test_data[] = {
- "", "",
- "a", "",
- "", "a",
- "a", "b",
- "a", "a",
- "ab", "aa",
- "abc", "ab",
- "abc", "abc",
- NULL,
- };
-
- for (unsigned i = 0; ; ++i) {
- if (!test_data[i*2])
- break;
- int libc_result = strcmp(test_data[i*2], test_data[i*2 + 1]);
- if (libc_result > 1)
- libc_result = 1;
- else if (libc_result < -1)
- libc_result = -1;
- ASSERT_EQ(my_strcmp(test_data[i*2], test_data[i*2 + 1]), libc_result);
- }
-}
-
-TEST(LinuxLibcSupportTest, strtoui) {
- int result;
-
- ASSERT_FALSE(my_strtoui(&result, ""));
- ASSERT_FALSE(my_strtoui(&result, "-1"));
- ASSERT_FALSE(my_strtoui(&result, "-"));
- ASSERT_FALSE(my_strtoui(&result, "a"));
- ASSERT_FALSE(my_strtoui(&result, "23472893472938472987987398472398"));
-
- ASSERT_TRUE(my_strtoui(&result, "0"));
- ASSERT_EQ(result, 0);
- ASSERT_TRUE(my_strtoui(&result, "1"));
- ASSERT_EQ(result, 1);
- ASSERT_TRUE(my_strtoui(&result, "12"));
- ASSERT_EQ(result, 12);
- ASSERT_TRUE(my_strtoui(&result, "123"));
- ASSERT_EQ(result, 123);
- ASSERT_TRUE(my_strtoui(&result, "0123"));
- ASSERT_EQ(result, 123);
-}
-
-TEST(LinuxLibcSupportTest, uint_len) {
- ASSERT_EQ(my_uint_len(0), 1U);
- ASSERT_EQ(my_uint_len(2), 1U);
- ASSERT_EQ(my_uint_len(5), 1U);
- ASSERT_EQ(my_uint_len(9), 1U);
- ASSERT_EQ(my_uint_len(10), 2U);
- ASSERT_EQ(my_uint_len(99), 2U);
- ASSERT_EQ(my_uint_len(100), 3U);
- ASSERT_EQ(my_uint_len(101), 3U);
- ASSERT_EQ(my_uint_len(1000), 4U);
- // 0xFFFFFFFFFFFFFFFF
- ASSERT_EQ(my_uint_len(18446744073709551615LLU), 20U);
-}
-
-TEST(LinuxLibcSupportTest, uitos) {
- char buf[32];
-
- my_uitos(buf, 0, 1);
- ASSERT_EQ(0, memcmp(buf, "0", 1));
-
- my_uitos(buf, 1, 1);
- ASSERT_EQ(0, memcmp(buf, "1", 1));
-
- my_uitos(buf, 10, 2);
- ASSERT_EQ(0, memcmp(buf, "10", 2));
-
- my_uitos(buf, 63, 2);
- ASSERT_EQ(0, memcmp(buf, "63", 2));
-
- my_uitos(buf, 101, 3);
- ASSERT_EQ(0, memcmp(buf, "101", 2));
-
- // 0xFFFFFFFFFFFFFFFF
- my_uitos(buf, 18446744073709551615LLU, 20);
- ASSERT_EQ(0, memcmp(buf, "18446744073709551615", 20));
-}
-
-TEST(LinuxLibcSupportTest, strchr) {
- ASSERT_EQ(NULL, my_strchr("abc", 'd'));
- ASSERT_EQ(NULL, my_strchr("", 'd'));
- ASSERT_EQ(NULL, my_strchr("efghi", 'd'));
-
- ASSERT_TRUE(my_strchr("a", 'a'));
- ASSERT_TRUE(my_strchr("abc", 'a'));
- ASSERT_TRUE(my_strchr("bcda", 'a'));
- ASSERT_TRUE(my_strchr("sdfasdf", 'a'));
-
- static const char abc3[] = "abcabcabc";
- ASSERT_EQ(abc3, my_strchr(abc3, 'a'));
-}
-
-TEST(LinuxLibcSupportTest, strrchr) {
- ASSERT_EQ(NULL, my_strrchr("abc", 'd'));
- ASSERT_EQ(NULL, my_strrchr("", 'd'));
- ASSERT_EQ(NULL, my_strrchr("efghi", 'd'));
-
- ASSERT_TRUE(my_strrchr("a", 'a'));
- ASSERT_TRUE(my_strrchr("abc", 'a'));
- ASSERT_TRUE(my_strrchr("bcda", 'a'));
- ASSERT_TRUE(my_strrchr("sdfasdf", 'a'));
-
- static const char abc3[] = "abcabcabc";
- ASSERT_EQ(abc3 + 6, my_strrchr(abc3, 'a'));
-}
-
-TEST(LinuxLibcSupportTest, memchr) {
- ASSERT_EQ(NULL, my_memchr("abc", 'd', 3));
- ASSERT_EQ(NULL, my_memchr("abcd", 'd', 3));
- ASSERT_EQ(NULL, my_memchr("a", 'a', 0));
-
- static const char abc3[] = "abcabcabc";
- ASSERT_EQ(abc3, my_memchr(abc3, 'a', 3));
- ASSERT_EQ(abc3, my_memchr(abc3, 'a', 9));
- ASSERT_EQ(abc3+1, my_memchr(abc3, 'b', 9));
- ASSERT_EQ(abc3+2, my_memchr(abc3, 'c', 9));
-}
-
-TEST(LinuxLibcSupportTest, read_hex_ptr) {
- uintptr_t result;
- const char* last;
-
- last = my_read_hex_ptr(&result, "");
- ASSERT_EQ(result, 0U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_hex_ptr(&result, "0");
- ASSERT_EQ(result, 0U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_hex_ptr(&result, "0123");
- ASSERT_EQ(result, 0x123U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_hex_ptr(&result, "0123a");
- ASSERT_EQ(result, 0x123aU);
- ASSERT_EQ(*last, 0);
-
- last = my_read_hex_ptr(&result, "0123a-");
- ASSERT_EQ(result, 0x123aU);
- ASSERT_EQ(*last, '-');
-}
-
-TEST(LinuxLibcSupportTest, read_decimal_ptr) {
- uintptr_t result;
- const char* last;
-
- last = my_read_decimal_ptr(&result, "0");
- ASSERT_EQ(result, 0U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_decimal_ptr(&result, "0123");
- ASSERT_EQ(result, 123U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_decimal_ptr(&result, "1234");
- ASSERT_EQ(result, 1234U);
- ASSERT_EQ(*last, 0);
-
- last = my_read_decimal_ptr(&result, "01234-");
- ASSERT_EQ(result, 1234U);
- ASSERT_EQ(*last, '-');
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc
deleted file mode 100644
index 4e938269f..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// 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.
-
-// memory_mapped_file.cc: Implement google_breakpad::MemoryMappedFile.
-// See memory_mapped_file.h for details.
-
-#include "common/linux/memory_mapped_file.h"
-
-#include <fcntl.h>
-#include <sys/mman.h>
-#if defined(__ANDROID__)
-#include <sys/stat.h>
-#endif
-#include <unistd.h>
-
-#include "common/memory_range.h"
-#include "third_party/lss/linux_syscall_support.h"
-
-namespace google_breakpad {
-
-MemoryMappedFile::MemoryMappedFile() {}
-
-MemoryMappedFile::MemoryMappedFile(const char* path, size_t offset) {
- Map(path, offset);
-}
-
-MemoryMappedFile::~MemoryMappedFile() {
- Unmap();
-}
-
-#include <unistd.h>
-
-bool MemoryMappedFile::Map(const char* path, size_t offset) {
- Unmap();
-
- int fd = sys_open(path, O_RDONLY, 0);
- if (fd == -1) {
- return false;
- }
-
-#if defined(__x86_64__) || defined(__aarch64__) || \
- (defined(__mips__) && _MIPS_SIM == _ABI64)
-
- struct kernel_stat st;
- if (sys_fstat(fd, &st) == -1 || st.st_size < 0) {
-#else
- struct kernel_stat64 st;
- if (sys_fstat64(fd, &st) == -1 || st.st_size < 0) {
-#endif
- sys_close(fd);
- return false;
- }
-
- // Strangely file size can be negative, but we check above that it is not.
- size_t file_len = static_cast<size_t>(st.st_size);
- // If the file does not extend beyond the offset, simply use an empty
- // MemoryRange and return true. Don't bother to call mmap()
- // even though mmap() can handle an empty file on some platforms.
- if (offset >= file_len) {
- sys_close(fd);
- return true;
- }
-
- void* data = sys_mmap(NULL, file_len, PROT_READ, MAP_PRIVATE, fd, offset);
- sys_close(fd);
- if (data == MAP_FAILED) {
- return false;
- }
-
- content_.Set(data, file_len - offset);
- return true;
-}
-
-void MemoryMappedFile::Unmap() {
- if (content_.data()) {
- sys_munmap(const_cast<uint8_t*>(content_.data()), content_.length());
- content_.Set(NULL, 0);
- }
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h
deleted file mode 100644
index fa660cc91..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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.
-
-// memory_mapped_file.h: Define the google_breakpad::MemoryMappedFile
-// class, which maps a file into memory for read-only access.
-
-#ifndef COMMON_LINUX_MEMORY_MAPPED_FILE_H_
-#define COMMON_LINUX_MEMORY_MAPPED_FILE_H_
-
-#include <stddef.h>
-#include "common/basictypes.h"
-#include "common/memory_range.h"
-
-namespace google_breakpad {
-
-// A utility class for mapping a file into memory for read-only access of
-// the file content. Its implementation avoids calling into libc functions
-// by directly making system calls for open, close, mmap, and munmap.
-class MemoryMappedFile {
- public:
- MemoryMappedFile();
-
- // Constructor that calls Map() to map a file at |path| into memory.
- // If Map() fails, the object behaves as if it is default constructed.
- MemoryMappedFile(const char* path, size_t offset);
-
- ~MemoryMappedFile();
-
- // Maps a file at |path| into memory, which can then be accessed via
- // content() as a MemoryRange object or via data(), and returns true on
- // success. Mapping an empty file will succeed but with data() and size()
- // returning NULL and 0, respectively. An existing mapping is unmapped
- // before a new mapping is created.
- bool Map(const char* path, size_t offset);
-
- // Unmaps the memory for the mapped file. It's a no-op if no file is
- // mapped.
- void Unmap();
-
- // Returns a MemoryRange object that covers the memory for the mapped
- // file. The MemoryRange object is empty if no file is mapped.
- const MemoryRange& content() const { return content_; }
-
- // Returns a pointer to the beginning of the memory for the mapped file.
- // or NULL if no file is mapped or the mapped file is empty.
- const void* data() const { return content_.data(); }
-
- // Returns the size in bytes of the mapped file, or zero if no file
- // is mapped.
- size_t size() const { return content_.length(); }
-
- private:
- // Mapped file content as a MemoryRange object.
- MemoryRange content_;
-
- DISALLOW_COPY_AND_ASSIGN(MemoryMappedFile);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_MEMORY_MAPPED_FILE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc
deleted file mode 100644
index fad59f40c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/memory_mapped_file_unittest.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-// 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.
-
-// memory_mapped_file_unittest.cc:
-// Unit tests for google_breakpad::MemoryMappedFile.
-
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/memory_mapped_file.h"
-#include "common/tests/auto_tempdir.h"
-#include "common/tests/file_utils.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::AutoTempDir;
-using google_breakpad::MemoryMappedFile;
-using google_breakpad::WriteFile;
-
-namespace {
-
-class MemoryMappedFileTest : public testing::Test {
- protected:
- void ExpectNoMappedData(const MemoryMappedFile& mapped_file) {
- EXPECT_TRUE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() == NULL);
- EXPECT_EQ(0U, mapped_file.size());
- }
-};
-
-} // namespace
-
-TEST_F(MemoryMappedFileTest, DefaultConstructor) {
- MemoryMappedFile mapped_file;
- ExpectNoMappedData(mapped_file);
-}
-
-TEST_F(MemoryMappedFileTest, UnmapWithoutMap) {
- MemoryMappedFile mapped_file;
- mapped_file.Unmap();
-}
-
-TEST_F(MemoryMappedFileTest, MapNonexistentFile) {
- {
- MemoryMappedFile mapped_file("nonexistent-file", 0);
- ExpectNoMappedData(mapped_file);
- }
- {
- MemoryMappedFile mapped_file;
- EXPECT_FALSE(mapped_file.Map("nonexistent-file", 0));
- ExpectNoMappedData(mapped_file);
- }
-}
-
-TEST_F(MemoryMappedFileTest, MapEmptyFile) {
- AutoTempDir temp_dir;
- string test_file = temp_dir.path() + "/empty_file";
- ASSERT_TRUE(WriteFile(test_file.c_str(), NULL, 0));
-
- {
- MemoryMappedFile mapped_file(test_file.c_str(), 0);
- ExpectNoMappedData(mapped_file);
- }
- {
- MemoryMappedFile mapped_file;
- EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0));
- ExpectNoMappedData(mapped_file);
- }
-}
-
-TEST_F(MemoryMappedFileTest, MapNonEmptyFile) {
- char data[256];
- size_t data_size = sizeof(data);
- for (size_t i = 0; i < data_size; ++i) {
- data[i] = i;
- }
-
- AutoTempDir temp_dir;
- string test_file = temp_dir.path() + "/test_file";
- ASSERT_TRUE(WriteFile(test_file.c_str(), data, data_size));
-
- {
- MemoryMappedFile mapped_file(test_file.c_str(), 0);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
- }
- {
- MemoryMappedFile mapped_file;
- EXPECT_TRUE(mapped_file.Map(test_file.c_str(), 0));
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data, mapped_file.data(), data_size));
- }
-}
-
-TEST_F(MemoryMappedFileTest, RemapAfterMap) {
- char data1[256];
- size_t data1_size = sizeof(data1);
- for (size_t i = 0; i < data1_size; ++i) {
- data1[i] = i;
- }
-
- char data2[50];
- size_t data2_size = sizeof(data2);
- for (size_t i = 0; i < data2_size; ++i) {
- data2[i] = 255 - i;
- }
-
- AutoTempDir temp_dir;
- string test_file1 = temp_dir.path() + "/test_file1";
- string test_file2 = temp_dir.path() + "/test_file2";
- ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size));
- ASSERT_TRUE(WriteFile(test_file2.c_str(), data2, data2_size));
-
- {
- MemoryMappedFile mapped_file(test_file1.c_str(), 0);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data1_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
-
- mapped_file.Map(test_file2.c_str(), 0);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data2_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
- }
- {
- MemoryMappedFile mapped_file;
- EXPECT_TRUE(mapped_file.Map(test_file1.c_str(), 0));
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data1_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data1, mapped_file.data(), data1_size));
-
- mapped_file.Map(test_file2.c_str(), 0);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data2_size, mapped_file.size());
- EXPECT_EQ(0, memcmp(data2, mapped_file.data(), data2_size));
- }
-}
-
-TEST_F(MemoryMappedFileTest, MapWithOffset) {
- // Put more data in the test file this time. Offsets can only be
- // done on page boundaries, so we need a two page file to test this.
- const int page_size = 4096;
- char data1[2 * page_size];
- size_t data1_size = sizeof(data1);
- for (size_t i = 0; i < data1_size; ++i) {
- data1[i] = i & 0x7f;
- }
-
- AutoTempDir temp_dir;
- string test_file1 = temp_dir.path() + "/test_file1";
- ASSERT_TRUE(WriteFile(test_file1.c_str(), data1, data1_size));
- {
- MemoryMappedFile mapped_file(test_file1.c_str(), page_size);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data1_size - page_size, mapped_file.size());
- EXPECT_EQ(
- 0,
- memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size));
- }
- {
- MemoryMappedFile mapped_file;
- mapped_file.Map(test_file1.c_str(), page_size);
- EXPECT_FALSE(mapped_file.content().IsEmpty());
- EXPECT_TRUE(mapped_file.data() != NULL);
- EXPECT_EQ(data1_size - page_size, mapped_file.size());
- EXPECT_EQ(
- 0,
- memcmp(data1 + page_size, mapped_file.data(), data1_size - page_size));
- }
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build b/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build
deleted file mode 100644
index 7450f6ba3..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/moz.build
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-UNIFIED_SOURCES += [
- 'elfutils.cc',
- 'guid_creator.cc',
- 'linux_libc_support.cc',
- 'memory_mapped_file.cc',
- 'safe_readlink.cc',
-]
-
-# file_id.cc cannot be built in unified mode because it uses a custom DISABLE_STL_WRAPPING
-SOURCES += [
- 'file_id.cc',
-]
-
-if CONFIG['OS_TARGET'] != 'Android':
- UNIFIED_SOURCES += [
- 'http_upload.cc',
- ]
-
-HostLibrary('host_breakpad_linux_common_s')
-HOST_SOURCES += [
- 'crc32.cc',
- 'dump_symbols.cc',
- 'elf_symbols_to_module.cc',
- 'elfutils.cc',
- 'file_id.cc',
- 'guid_creator.cc',
- 'linux_libc_support.cc',
- 'memory_mapped_file.cc',
-]
-
-HOST_CXXFLAGS += [
- '-O2',
- '-g',
-]
-
-if CONFIG['OS_TARGET'] == 'Android':
- LOCAL_INCLUDES += [
- '/toolkit/crashreporter/google-breakpad/src/common/android/include',
- ]
-
-Library('breakpad_linux_common_s')
-
-FINAL_LIBRARY = 'xul'
-
-HOST_DEFINES['NO_STABS_SUPPORT'] = True
-
-include('/toolkit/crashreporter/crashreporter.mozbuild')
-
-if CONFIG['GNU_CXX']:
- CXXFLAGS += ['-Wno-shadow']
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc
deleted file mode 100644
index 870c28af3..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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.
-
-// safe_readlink.cc: Implement google_breakpad::SafeReadLink.
-// See safe_readlink.h for details.
-
-#include <stddef.h>
-
-#include "third_party/lss/linux_syscall_support.h"
-
-namespace google_breakpad {
-
-bool SafeReadLink(const char* path, char* buffer, size_t buffer_size) {
- // sys_readlink() does not add a NULL byte to |buffer|. In order to return
- // a NULL-terminated string in |buffer|, |buffer_size| should be at least
- // one byte longer than the expected path length. Also, sys_readlink()
- // returns the actual path length on success, which does not count the
- // NULL byte, so |result_size| should be less than |buffer_size|.
- ssize_t result_size = sys_readlink(path, buffer, buffer_size);
- if (result_size >= 0 && static_cast<size_t>(result_size) < buffer_size) {
- buffer[result_size] = '\0';
- return true;
- }
- return false;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h
deleted file mode 100644
index 4ae131b58..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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.
-
-// safe_readlink.h: Define the google_breakpad::SafeReadLink function,
-// which wraps sys_readlink and gurantees the result is NULL-terminated.
-
-#ifndef COMMON_LINUX_SAFE_READLINK_H_
-#define COMMON_LINUX_SAFE_READLINK_H_
-
-#include <stddef.h>
-
-namespace google_breakpad {
-
-// This function wraps sys_readlink() and performs the same functionalty,
-// but guarantees |buffer| is NULL-terminated if sys_readlink() returns
-// no error. It takes the same arguments as sys_readlink(), but unlike
-// sys_readlink(), it returns true on success.
-//
-// |buffer_size| specifies the size of |buffer| in bytes. As this function
-// always NULL-terminates |buffer| on success, |buffer_size| should be
-// at least one byte longer than the expected path length (e.g. PATH_MAX,
-// which is typically defined as the maximum length of a path name
-// including the NULL byte).
-//
-// The implementation of this function calls sys_readlink() instead of
-// readlink(), it can thus be used in the context where calling to libc
-// functions is discouraged.
-bool SafeReadLink(const char* path, char* buffer, size_t buffer_size);
-
-// Same as the three-argument version of SafeReadLink() but deduces the
-// size of |buffer| if it is a char array of known size.
-template <size_t N>
-bool SafeReadLink(const char* path, char (&buffer)[N]) {
- return SafeReadLink(path, buffer, sizeof(buffer));
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_SAFE_READLINK_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc
deleted file mode 100644
index d346b2a80..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/safe_readlink_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.
-
-// safe_readlink_unittest.cc: Unit tests for google_breakpad::SafeReadLink.
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/safe_readlink.h"
-
-using google_breakpad::SafeReadLink;
-
-TEST(SafeReadLinkTest, ZeroBufferSize) {
- char buffer[1];
- EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, 0));
-}
-
-TEST(SafeReadLinkTest, BufferSizeTooSmall) {
- char buffer[1];
- EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, 1));
-}
-
-TEST(SafeReadLinkTest, BoundaryBufferSize) {
- char buffer[PATH_MAX];
- EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer, sizeof(buffer)));
- size_t path_length = strlen(buffer);
- EXPECT_LT(0U, path_length);
- EXPECT_GT(sizeof(buffer), path_length);
-
- // Buffer size equals to the expected path length plus 1 for the NULL byte.
- char buffer2[PATH_MAX];
- EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer2, path_length + 1));
- EXPECT_EQ(path_length, strlen(buffer2));
- EXPECT_EQ(0, strncmp(buffer, buffer2, PATH_MAX));
-
- // Buffer size equals to the expected path length.
- EXPECT_FALSE(SafeReadLink("/proc/self/exe", buffer, path_length));
-}
-
-TEST(SafeReadLinkTest, NonexistentPath) {
- char buffer[PATH_MAX];
- EXPECT_FALSE(SafeReadLink("nonexistent_path", buffer, sizeof(buffer)));
-}
-
-TEST(SafeReadLinkTest, NonSymbolicLinkPath) {
- char actual_path[PATH_MAX];
- EXPECT_TRUE(SafeReadLink("/proc/self/exe", actual_path, sizeof(actual_path)));
-
- char buffer[PATH_MAX];
- EXPECT_FALSE(SafeReadLink(actual_path, buffer, sizeof(buffer)));
-}
-
-TEST(SafeReadLinkTest, DeduceBufferSizeFromCharArray) {
- char buffer[PATH_MAX];
- char* buffer_pointer = buffer;
- EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer_pointer, sizeof(buffer)));
- size_t path_length = strlen(buffer);
-
- // Use the template version of SafeReadLink to deduce the buffer size
- // from the char array.
- char buffer2[PATH_MAX];
- EXPECT_TRUE(SafeReadLink("/proc/self/exe", buffer2));
- EXPECT_EQ(path_length, strlen(buffer2));
- EXPECT_EQ(0, strncmp(buffer, buffer2, PATH_MAX));
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc
deleted file mode 100644
index bbd3181e1..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// 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.
-
-// symbol_upload.cc: implemented google_breakpad::sym_upload::Start, a helper
-// function for linux symbol upload tool.
-
-#include "common/linux/http_upload.h"
-#include "common/linux/symbol_upload.h"
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <functional>
-#include <vector>
-
-namespace google_breakpad {
-namespace sym_upload {
-
-void TokenizeByChar(const string &source_string, int c,
- std::vector<string> *results) {
- assert(results);
- string::size_type cur_pos = 0, next_pos = 0;
- while ((next_pos = source_string.find(c, cur_pos)) != string::npos) {
- if (next_pos != cur_pos)
- results->push_back(source_string.substr(cur_pos, next_pos - cur_pos));
- cur_pos = next_pos + 1;
- }
- if (cur_pos < source_string.size() && next_pos != cur_pos)
- results->push_back(source_string.substr(cur_pos));
-}
-
-//=============================================================================
-// Parse out the module line which have 5 parts.
-// MODULE <os> <cpu> <uuid> <module-name>
-bool ModuleDataForSymbolFile(const string &file,
- std::vector<string> *module_parts) {
- assert(module_parts);
- const size_t kModulePartNumber = 5;
- FILE* fp = fopen(file.c_str(), "r");
- if (fp) {
- char buffer[1024];
- if (fgets(buffer, sizeof(buffer), fp)) {
- string line(buffer);
- string::size_type line_break_pos = line.find_first_of('\n');
- if (line_break_pos == string::npos) {
- assert(0 && "The file is invalid!");
- fclose(fp);
- return false;
- }
- line.resize(line_break_pos);
- const char kDelimiter = ' ';
- TokenizeByChar(line, kDelimiter, module_parts);
- if (module_parts->size() != kModulePartNumber)
- module_parts->clear();
- }
- fclose(fp);
- }
-
- return module_parts->size() == kModulePartNumber;
-}
-
-//=============================================================================
-string CompactIdentifier(const string &uuid) {
- std::vector<string> components;
- TokenizeByChar(uuid, '-', &components);
- string result;
- for (size_t i = 0; i < components.size(); ++i)
- result += components[i];
- return result;
-}
-
-//=============================================================================
-void Start(Options *options) {
- std::map<string, string> parameters;
- options->success = false;
- std::vector<string> module_parts;
- if (!ModuleDataForSymbolFile(options->symbolsPath, &module_parts)) {
- fprintf(stderr, "Failed to parse symbol file!\n");
- return;
- }
-
- string compacted_id = CompactIdentifier(module_parts[3]);
-
- // Add parameters
- if (!options->version.empty())
- parameters["version"] = options->version;
-
- // MODULE <os> <cpu> <uuid> <module-name>
- // 0 1 2 3 4
- parameters["os"] = module_parts[1];
- parameters["cpu"] = module_parts[2];
- parameters["debug_file"] = module_parts[4];
- parameters["code_file"] = module_parts[4];
- parameters["debug_identifier"] = compacted_id;
-
- std::map<string, string> files;
- files["symbol_file"] = options->symbolsPath;
-
- string response, error;
- long response_code;
- bool success = HTTPUpload::SendRequest(options->uploadURLStr,
- parameters,
- files,
- options->proxy,
- options->proxy_user_pwd,
- "",
- &response,
- &response_code,
- &error);
-
- if (!success) {
- printf("Failed to send symbol file: %s\n", error.c_str());
- printf("Response code: %ld\n", response_code);
- printf("Response:\n");
- printf("%s\n", response.c_str());
- } else if (response_code == 0) {
- printf("Failed to send symbol file: No response code\n");
- } else if (response_code != 200) {
- printf("Failed to send symbol file: Response code %ld\n", response_code);
- printf("Response:\n");
- printf("%s\n", response.c_str());
- } else {
- printf("Successfully sent the symbol file.\n");
- }
- options->success = success;
-}
-
-} // namespace sym_upload
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h b/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h
deleted file mode 100644
index 0a469692a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/symbol_upload.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// symbol_upload.h: helper functions for linux symbol upload tool.
-
-#ifndef COMMON_LINUX_SYMBOL_UPLOAD_H_
-#define COMMON_LINUX_SYMBOL_UPLOAD_H_
-
-#include <string>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-namespace sym_upload {
-
-typedef struct {
- string symbolsPath;
- string uploadURLStr;
- string proxy;
- string proxy_user_pwd;
- string version;
- bool success;
-} Options;
-
-// Starts upload to symbol server with options.
-void Start(Options* options);
-
-} // namespace sym_upload
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_SYMBOL_UPLOAD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc
deleted file mode 100644
index 98e81dab7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.cc
+++ /dev/null
@@ -1,263 +0,0 @@
-#include "common/linux/synth_elf.h"
-
-#include <assert.h>
-#include <elf.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "common/linux/elf_gnu_compat.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-namespace synth_elf {
-
-ELF::ELF(uint16_t machine,
- uint8_t file_class,
- Endianness endianness)
- : Section(endianness),
- addr_size_(file_class == ELFCLASS64 ? 8 : 4),
- program_count_(0),
- program_header_table_(endianness),
- section_count_(0),
- section_header_table_(endianness),
- section_header_strings_(endianness) {
- // Could add support for more machine types here if needed.
- assert(machine == EM_386 ||
- machine == EM_X86_64 ||
- machine == EM_ARM);
- assert(file_class == ELFCLASS32 || file_class == ELFCLASS64);
-
- start() = 0;
- // Add ELF header
- // e_ident
- // EI_MAG0...EI_MAG3
- D8(ELFMAG0);
- D8(ELFMAG1);
- D8(ELFMAG2);
- D8(ELFMAG3);
- // EI_CLASS
- D8(file_class);
- // EI_DATA
- D8(endianness == kLittleEndian ? ELFDATA2LSB : ELFDATA2MSB);
- // EI_VERSION
- D8(EV_CURRENT);
- // EI_OSABI
- D8(ELFOSABI_SYSV);
- // EI_ABIVERSION
- D8(0);
- // EI_PAD
- Append(7, 0);
- assert(Size() == EI_NIDENT);
-
- // e_type
- D16(ET_EXEC); //TODO: allow passing ET_DYN?
- // e_machine
- D16(machine);
- // e_version
- D32(EV_CURRENT);
- // e_entry
- Append(endianness, addr_size_, 0);
- // e_phoff
- Append(endianness, addr_size_, program_header_label_);
- // e_shoff
- Append(endianness, addr_size_, section_header_label_);
- // e_flags
- D32(0);
- // e_ehsize
- D16(addr_size_ == 8 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr));
- // e_phentsize
- D16(addr_size_ == 8 ? sizeof(Elf64_Phdr) : sizeof(Elf32_Phdr));
- // e_phnum
- D16(program_count_label_);
- // e_shentsize
- D16(addr_size_ == 8 ? sizeof(Elf64_Shdr) : sizeof(Elf32_Shdr));
- // e_shnum
- D16(section_count_label_);
- // e_shstrndx
- D16(section_header_string_index_);
-
- // Add an empty section for SHN_UNDEF.
- Section shn_undef;
- AddSection("", shn_undef, SHT_NULL);
-}
-
-int ELF::AddSection(const string& name, const Section& section,
- uint32_t type, uint32_t flags, uint64_t addr,
- uint32_t link, uint64_t entsize, uint64_t offset) {
- Label offset_label;
- Label string_label(section_header_strings_.Add(name));
- size_t size = section.Size();
-
- int index = section_count_;
- ++section_count_;
-
- section_header_table_
- // sh_name
- .D32(string_label)
- // sh_type
- .D32(type)
- // sh_flags
- .Append(endianness(), addr_size_, flags)
- // sh_addr
- .Append(endianness(), addr_size_, addr)
- // sh_offset
- .Append(endianness(), addr_size_, offset_label)
- // sh_size
- .Append(endianness(), addr_size_, size)
- // sh_link
- .D32(link)
- // sh_info
- .D32(0)
- // sh_addralign
- .Append(endianness(), addr_size_, 0)
- // sh_entsize
- .Append(endianness(), addr_size_, entsize);
-
- sections_.push_back(ElfSection(section, type, addr, offset, offset_label,
- size));
- return index;
-}
-
-void ELF::AppendSection(ElfSection &section) {
- // NULL and NOBITS sections have no content, so they
- // don't need to be written to the file.
- if (section.type_ == SHT_NULL) {
- section.offset_label_ = 0;
- } else if (section.type_ == SHT_NOBITS) {
- section.offset_label_ = section.offset_;
- } else {
- Mark(&section.offset_label_);
- Append(section);
- Align(4);
- }
-}
-
-void ELF::AddSegment(int start, int end, uint32_t type, uint32_t flags) {
- assert(start > 0);
- assert(size_t(start) < sections_.size());
- assert(end > 0);
- assert(size_t(end) < sections_.size());
- ++program_count_;
-
- // p_type
- program_header_table_.D32(type);
-
- if (addr_size_ == 8) {
- // p_flags
- program_header_table_.D32(flags);
- }
-
- size_t filesz = 0;
- size_t memsz = 0;
- bool prev_was_nobits = false;
- for (int i = start; i <= end; ++i) {
- size_t size = sections_[i].size_;
- if (sections_[i].type_ != SHT_NOBITS) {
- assert(!prev_was_nobits);
- // non SHT_NOBITS sections are 4-byte aligned (see AddSection)
- size = (size + 3) & ~3;
- filesz += size;
- } else {
- prev_was_nobits = true;
- }
- memsz += size;
- }
-
- program_header_table_
- // p_offset
- .Append(endianness(), addr_size_, sections_[start].offset_label_)
- // p_vaddr
- .Append(endianness(), addr_size_, sections_[start].addr_)
- // p_paddr
- .Append(endianness(), addr_size_, sections_[start].addr_)
- // p_filesz
- .Append(endianness(), addr_size_, filesz)
- // p_memsz
- .Append(endianness(), addr_size_, memsz);
-
- if (addr_size_ == 4) {
- // p_flags
- program_header_table_.D32(flags);
- }
-
- // p_align
- program_header_table_.Append(endianness(), addr_size_, 0);
-}
-
-void ELF::Finish() {
- // Add the section header string table at the end.
- section_header_string_index_ = section_count_;
- //printf(".shstrtab size: %ld\n", section_header_strings_.Size());
- AddSection(".shstrtab", section_header_strings_, SHT_STRTAB);
- //printf("section_count_: %ld, sections_.size(): %ld\n",
- // section_count_, sections_.size());
- if (program_count_) {
- Mark(&program_header_label_);
- Append(program_header_table_);
- } else {
- program_header_label_ = 0;
- }
-
- for (vector<ElfSection>::iterator it = sections_.begin();
- it < sections_.end(); ++it) {
- AppendSection(*it);
- }
- section_count_label_ = section_count_;
- program_count_label_ = program_count_;
-
- // Section header table starts here.
- Mark(&section_header_label_);
- Append(section_header_table_);
-}
-
-SymbolTable::SymbolTable(Endianness endianness,
- size_t addr_size,
- StringTable& table) : Section(endianness),
- table_(table) {
-#ifndef NDEBUG
- addr_size_ = addr_size;
-#endif
- assert(addr_size_ == 4 || addr_size_ == 8);
-}
-
-void SymbolTable::AddSymbol(const string& name, uint32_t value,
- uint32_t size, unsigned info, uint16_t shndx) {
- assert(addr_size_ == 4);
- D32(table_.Add(name));
- D32(value);
- D32(size);
- D8(info);
- D8(0); // other
- D16(shndx);
-}
-
-void SymbolTable::AddSymbol(const string& name, uint64_t value,
- uint64_t size, unsigned info, uint16_t shndx) {
- assert(addr_size_ == 8);
- D32(table_.Add(name));
- D8(info);
- D8(0); // other
- D16(shndx);
- D64(value);
- D64(size);
-}
-
-void Notes::AddNote(int type, const string &name, const uint8_t* desc_bytes,
- size_t desc_size) {
- // Elf32_Nhdr and Elf64_Nhdr are exactly the same.
- Elf32_Nhdr note_header;
- memset(&note_header, 0, sizeof(note_header));
- note_header.n_namesz = name.length() + 1;
- note_header.n_descsz = desc_size;
- note_header.n_type = type;
-
- Append(reinterpret_cast<const uint8_t*>(&note_header),
- sizeof(note_header));
- AppendCString(name);
- Align(4);
- Append(desc_bytes, desc_size);
- Align(4);
-}
-
-} // namespace synth_elf
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h
deleted file mode 100644
index 1d2a20ca2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-// synth_elf.h: Interface to synth_elf::ELF: fake ELF generator.
-
-#ifndef COMMON_LINUX_SYNTH_ELF_H_
-#define COMMON_LINUX_SYNTH_ELF_H_
-
-#include "common/test_assembler.h"
-
-#include <list>
-#include <vector>
-#include <map>
-#include <string>
-#include <utility>
-
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-namespace synth_elf {
-
-using std::list;
-using std::vector;
-using std::map;
-using std::pair;
-using test_assembler::Endianness;
-using test_assembler::kLittleEndian;
-using test_assembler::kUnsetEndian;
-using test_assembler::Label;
-using test_assembler::Section;
-
-// String tables are common in ELF headers, so subclass Section
-// to make them easy to generate.
-class StringTable : public Section {
-public:
- StringTable(Endianness endianness = kUnsetEndian)
- : Section(endianness) {
- start() = 0;
- empty_string = Add("");
- }
-
- // Add the string s to the string table, and return
- // a label containing the offset into the string table
- // at which it was added.
- Label Add(const string& s) {
- if (strings_.find(s) != strings_.end())
- return strings_[s];
-
- Label string_label(Here());
- AppendCString(s);
- strings_[s] = string_label;
- return string_label;
- }
-
- // All StringTables contain an empty string as their first
- // entry.
- Label empty_string;
-
- // Avoid inserting duplicate strings.
- map<string,Label> strings_;
-};
-
-// A Section representing an entire ELF file.
-class ELF : public Section {
- public:
- ELF(uint16_t machine, // EM_386, etc
- uint8_t file_class, // ELFCLASS{32,64}
- Endianness endianness = kLittleEndian);
-
- // Add the Section section to the section header table and append it
- // to the file. Returns the index of the section in the section
- // header table.
- int AddSection(const string& name, const Section& section,
- uint32_t type, uint32_t flags = 0, uint64_t addr = 0,
- uint32_t link = 0, uint64_t entsize = 0, uint64_t offset = 0);
-
- // Add a segment containing from section index start to section index end.
- // The indexes must have been gotten from AddSection.
- void AddSegment(int start, int end, uint32_t type, uint32_t flags = 0);
-
- // Write out all data. GetContents may be used after this.
- void Finish();
-
- private:
- // Size of an address, in bytes.
- const size_t addr_size_;
-
- // Offset to the program header table.
- Label program_header_label_;
- // Number of entries in the program header table.
- int program_count_;
- Label program_count_label_;
- // The program header table itself.
- Section program_header_table_;
-
- // Offset to the section header table.
- Label section_header_label_;
- // Number of entries in the section header table.
- int section_count_;
- Label section_count_label_;
- // The section header table itself.
- Section section_header_table_;
-
- // Index of the section header string table in the section
- // header table.
- Label section_header_string_index_;
- // Section containing the names of section header table entries.
- StringTable section_header_strings_;
-
- // Record of an added section
- struct ElfSection : public Section {
- ElfSection(const Section& section, uint32_t type, uint32_t addr,
- uint32_t offset, Label offset_label, uint32_t size)
- : Section(section), type_(type), addr_(addr), offset_(offset)
- , offset_label_(offset_label), size_(size) {
- }
-
- uint32_t type_;
- uint32_t addr_;
- uint32_t offset_;
- Label offset_label_;
- uint32_t size_;
- };
-
- vector<ElfSection> sections_;
-
- void AppendSection(ElfSection &section);
-};
-
-// A class to build .symtab or .dynsym sections.
-class SymbolTable : public Section {
- public:
- // table is the StringTable that contains symbol names. The caller
- // must ensure that it remains alive for the life of the
- // SymbolTable.
- SymbolTable(Endianness endianness, size_t addr_size, StringTable& table);
-
- // Add an Elf32_Sym.
- void AddSymbol(const string& name, uint32_t value,
- uint32_t size, unsigned info, uint16_t shndx);
- // Add an Elf64_Sym.
- void AddSymbol(const string& name, uint64_t value,
- uint64_t size, unsigned info, uint16_t shndx);
-
- private:
-#ifndef NDEBUG
- size_t addr_size_;
-#endif
- StringTable& table_;
-};
-
-// A class for note sections
-class Notes : public Section {
-public:
- Notes(Endianness endianness)
- : Section(endianness) {
- }
-
- // Add a note.
- void AddNote(int type, const string &name, const uint8_t* desc_bytes,
- size_t desc_size);
-};
-
-} // namespace synth_elf
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_SYNTH_ELF_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc
deleted file mode 100644
index 3715b6e60..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/synth_elf_unittest.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-// 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.
-
-// Original author: Ted Mielczarek <ted.mielczarek@gmail.com>
-
-// synth_elf_unittest.cc:
-// Unittests for google_breakpad::synth_elf::ELF
-
-#include <elf.h>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/elfutils.h"
-#include "common/linux/synth_elf.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::ElfClass32;
-using google_breakpad::ElfClass64;
-using google_breakpad::synth_elf::ELF;
-using google_breakpad::synth_elf::Notes;
-using google_breakpad::synth_elf::Section;
-using google_breakpad::synth_elf::StringTable;
-using google_breakpad::synth_elf::SymbolTable;
-using google_breakpad::test_assembler::Endianness;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using google_breakpad::test_assembler::Label;
-using ::testing::Test;
-using ::testing::Types;
-
-class StringTableTest : public Test {
-public:
- StringTableTest() : table(kLittleEndian) {}
-
- StringTable table;
-};
-
-TEST_F(StringTableTest, Empty) {
- EXPECT_EQ(1U, table.Size());
- string contents;
- ASSERT_TRUE(table.GetContents(&contents));
- const char* kExpectedContents = "\0";
- EXPECT_EQ(0, memcmp(kExpectedContents,
- contents.c_str(),
- contents.size()));
- ASSERT_TRUE(table.empty_string.IsKnownConstant());
- EXPECT_EQ(0U, table.empty_string.Value());
-}
-
-TEST_F(StringTableTest, Basic) {
- const string s1("table fills with strings");
- const string s2("offsets preserved as labels");
- const string s3("verified with tests");
- const char* kExpectedContents =
- "\0table fills with strings\0"
- "offsets preserved as labels\0"
- "verified with tests\0";
- Label l1(table.Add(s1));
- Label l2(table.Add(s2));
- Label l3(table.Add(s3));
- string contents;
- ASSERT_TRUE(table.GetContents(&contents));
- EXPECT_EQ(0, memcmp(kExpectedContents,
- contents.c_str(),
- contents.size()));
- // empty_string is at zero, other strings start at 1.
- ASSERT_TRUE(l1.IsKnownConstant());
- EXPECT_EQ(1U, l1.Value());
- // Each string has an extra byte for a trailing null.
- EXPECT_EQ(1 + s1.length() + 1, l2.Value());
- EXPECT_EQ(1 + s1.length() + 1 + s2.length() + 1, l3.Value());
-}
-
-TEST_F(StringTableTest, Duplicates) {
- const string s1("string 1");
- const string s2("string 2");
- const string s3("");
- const char* kExpectedContents = "\0string 1\0string 2\0";
- Label l1(table.Add(s1));
- Label l2(table.Add(s2));
- // Adding strings twice should return the same Label.
- Label l3(table.Add(s3));
- Label l4(table.Add(s2));
- string contents;
- ASSERT_TRUE(table.GetContents(&contents));
- EXPECT_EQ(0, memcmp(kExpectedContents,
- contents.c_str(),
- contents.size()));
- EXPECT_EQ(0U, table.empty_string.Value());
- EXPECT_EQ(table.empty_string.Value(), l3.Value());
- EXPECT_EQ(l2.Value(), l4.Value());
-}
-
-class SymbolTableTest : public Test {};
-
-TEST_F(SymbolTableTest, Simple32) {
- StringTable table(kLittleEndian);
- SymbolTable syms(kLittleEndian, 4, table);
-
- const string kFuncName1 = "superfunc";
- const uint32_t kFuncAddr1 = 0x10001000;
- const uint32_t kFuncSize1 = 0x10;
- const string kFuncName2 = "awesomefunc";
- const uint32_t kFuncAddr2 = 0x20002000;
- const uint32_t kFuncSize2 = 0x2f;
- const string kFuncName3 = "megafunc";
- const uint32_t kFuncAddr3 = 0x30003000;
- const uint32_t kFuncSize3 = 0x3c;
-
- syms.AddSymbol(kFuncName1, kFuncAddr1, kFuncSize1,
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC),
- SHN_UNDEF + 1);
- syms.AddSymbol(kFuncName2, kFuncAddr2, kFuncSize2,
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
- SHN_UNDEF + 2);
- syms.AddSymbol(kFuncName3, kFuncAddr3, kFuncSize3,
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC),
- SHN_UNDEF + 3);
-
- const char kExpectedStringTable[] = "\0superfunc\0awesomefunc\0megafunc";
- const size_t kExpectedStringTableSize = sizeof(kExpectedStringTable);
- EXPECT_EQ(kExpectedStringTableSize, table.Size());
- string table_contents;
- table.GetContents(&table_contents);
- EXPECT_EQ(0, memcmp(kExpectedStringTable,
- table_contents.c_str(),
- table_contents.size()));
-
- const uint8_t kExpectedSymbolContents[] = {
- // Symbol 1
- 0x01, 0x00, 0x00, 0x00, // name
- 0x00, 0x10, 0x00, 0x10, // value
- 0x10, 0x00, 0x00, 0x00, // size
- ELF32_ST_INFO(STB_GLOBAL, STT_FUNC), // info
- 0x00, // other
- 0x01, 0x00, // shndx
- // Symbol 2
- 0x0B, 0x00, 0x00, 0x00, // name
- 0x00, 0x20, 0x00, 0x20, // value
- 0x2f, 0x00, 0x00, 0x00, // size
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
- 0x00, // other
- 0x02, 0x00, // shndx
- // Symbol 3
- 0x17, 0x00, 0x00, 0x00, // name
- 0x00, 0x30, 0x00, 0x30, // value
- 0x3c, 0x00, 0x00, 0x00, // size
- ELF32_ST_INFO(STB_LOCAL, STT_FUNC), // info
- 0x00, // other
- 0x03, 0x00, // shndx
- };
- const size_t kExpectedSymbolSize = sizeof(kExpectedSymbolContents);
- EXPECT_EQ(kExpectedSymbolSize, syms.Size());
-
- string symbol_contents;
- syms.GetContents(&symbol_contents);
- EXPECT_EQ(0, memcmp(kExpectedSymbolContents,
- symbol_contents.c_str(),
- symbol_contents.size()));
-}
-
-template<typename ElfClass>
-class BasicElf : public Test {};
-
-// Doesn't seem worthwhile writing the tests to be endian-independent
-// when they're unlikely to ever be run on big-endian systems.
-#if defined(__i386__) || defined(__x86_64__)
-
-typedef Types<ElfClass32, ElfClass64> ElfClasses;
-
-TYPED_TEST_CASE(BasicElf, ElfClasses);
-
-TYPED_TEST(BasicElf, EmptyLE) {
- typedef typename TypeParam::Ehdr Ehdr;
- typedef typename TypeParam::Phdr Phdr;
- typedef typename TypeParam::Shdr Shdr;
- const size_t kStringTableSize = sizeof("\0.shstrtab");
- const size_t kStringTableAlign = 4 - kStringTableSize % 4;
- const size_t kExpectedSize = sizeof(Ehdr) +
- // Two sections, SHT_NULL + the section header string table.
- 2 * sizeof(Shdr) +
- kStringTableSize + kStringTableAlign;
-
- // It doesn't really matter that the machine type is right for the class.
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- elf.Finish();
- EXPECT_EQ(kExpectedSize, elf.Size());
-
- string contents;
- ASSERT_TRUE(elf.GetContents(&contents));
- ASSERT_EQ(kExpectedSize, contents.size());
- const Ehdr* header =
- reinterpret_cast<const Ehdr*>(contents.data());
- const uint8_t kIdent[] = {
- ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
- TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
- EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
- EXPECT_EQ(ET_EXEC, header->e_type);
- EXPECT_EQ(EM_386, header->e_machine);
- EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version);
- EXPECT_EQ(0U, header->e_entry);
- EXPECT_EQ(0U, header->e_phoff);
- EXPECT_EQ(sizeof(Ehdr) + kStringTableSize + kStringTableAlign,
- header->e_shoff);
- EXPECT_EQ(0U, header->e_flags);
- EXPECT_EQ(sizeof(Ehdr), header->e_ehsize);
- EXPECT_EQ(sizeof(Phdr), header->e_phentsize);
- EXPECT_EQ(0, header->e_phnum);
- EXPECT_EQ(sizeof(Shdr), header->e_shentsize);
- EXPECT_EQ(2, header->e_shnum);
- EXPECT_EQ(1, header->e_shstrndx);
-
- const Shdr* shdr =
- reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff);
- EXPECT_EQ(0U, shdr[0].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type);
- EXPECT_EQ(0U, shdr[0].sh_flags);
- EXPECT_EQ(0U, shdr[0].sh_addr);
- EXPECT_EQ(0U, shdr[0].sh_offset);
- EXPECT_EQ(0U, shdr[0].sh_size);
- EXPECT_EQ(0U, shdr[0].sh_link);
- EXPECT_EQ(0U, shdr[0].sh_info);
- EXPECT_EQ(0U, shdr[0].sh_addralign);
- EXPECT_EQ(0U, shdr[0].sh_entsize);
-
- EXPECT_EQ(1U, shdr[1].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[1].sh_type);
- EXPECT_EQ(0U, shdr[1].sh_flags);
- EXPECT_EQ(0U, shdr[1].sh_addr);
- EXPECT_EQ(sizeof(Ehdr), shdr[1].sh_offset);
- EXPECT_EQ(kStringTableSize, shdr[1].sh_size);
- EXPECT_EQ(0U, shdr[1].sh_link);
- EXPECT_EQ(0U, shdr[1].sh_info);
- EXPECT_EQ(0U, shdr[1].sh_addralign);
- EXPECT_EQ(0U, shdr[1].sh_entsize);
-}
-
-TYPED_TEST(BasicElf, BasicLE) {
- typedef typename TypeParam::Ehdr Ehdr;
- typedef typename TypeParam::Phdr Phdr;
- typedef typename TypeParam::Shdr Shdr;
- const size_t kStringTableSize = sizeof("\0.text\0.bss\0.shstrtab");
- const size_t kStringTableAlign = 4 - kStringTableSize % 4;
- const size_t kExpectedSize = sizeof(Ehdr) +
- // Four sections, SHT_NULL + the section header string table +
- // 4096 bytes of the size-aligned .text section + one program header.
- sizeof(Phdr) + 4 * sizeof(Shdr) + 4096 +
- kStringTableSize + kStringTableAlign;
-
- // It doesn't really matter that the machine type is right for the class.
- ELF elf(EM_386, TypeParam::kClass, kLittleEndian);
- Section text(kLittleEndian);
- text.Append(4094, 0);
- int text_idx = elf.AddSection(".text", text, SHT_PROGBITS);
- Section bss(kLittleEndian);
- bss.Append(16, 0);
- int bss_idx = elf.AddSection(".bss", bss, SHT_NOBITS);
- elf.AddSegment(text_idx, bss_idx, PT_LOAD);
- elf.Finish();
- EXPECT_EQ(kExpectedSize, elf.Size());
-
- string contents;
- ASSERT_TRUE(elf.GetContents(&contents));
- ASSERT_EQ(kExpectedSize, contents.size());
- const Ehdr* header =
- reinterpret_cast<const Ehdr*>(contents.data());
- const uint8_t kIdent[] = {
- ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
- TypeParam::kClass, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
- EXPECT_EQ(0, memcmp(kIdent, header->e_ident, sizeof(kIdent)));
- EXPECT_EQ(ET_EXEC, header->e_type);
- EXPECT_EQ(EM_386, header->e_machine);
- EXPECT_EQ(static_cast<unsigned int>(EV_CURRENT), header->e_version);
- EXPECT_EQ(0U, header->e_entry);
- EXPECT_EQ(sizeof(Ehdr), header->e_phoff);
- EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096 + kStringTableSize +
- kStringTableAlign, header->e_shoff);
- EXPECT_EQ(0U, header->e_flags);
- EXPECT_EQ(sizeof(Ehdr), header->e_ehsize);
- EXPECT_EQ(sizeof(Phdr), header->e_phentsize);
- EXPECT_EQ(1, header->e_phnum);
- EXPECT_EQ(sizeof(Shdr), header->e_shentsize);
- EXPECT_EQ(4, header->e_shnum);
- EXPECT_EQ(3, header->e_shstrndx);
-
- const Shdr* shdr =
- reinterpret_cast<const Shdr*>(contents.data() + header->e_shoff);
- EXPECT_EQ(0U, shdr[0].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_NULL), shdr[0].sh_type);
- EXPECT_EQ(0U, shdr[0].sh_flags);
- EXPECT_EQ(0U, shdr[0].sh_addr);
- EXPECT_EQ(0U, shdr[0].sh_offset);
- EXPECT_EQ(0U, shdr[0].sh_size);
- EXPECT_EQ(0U, shdr[0].sh_link);
- EXPECT_EQ(0U, shdr[0].sh_info);
- EXPECT_EQ(0U, shdr[0].sh_addralign);
- EXPECT_EQ(0U, shdr[0].sh_entsize);
-
- EXPECT_EQ(1U, shdr[1].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_PROGBITS), shdr[1].sh_type);
- EXPECT_EQ(0U, shdr[1].sh_flags);
- EXPECT_EQ(0U, shdr[1].sh_addr);
- EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), shdr[1].sh_offset);
- EXPECT_EQ(4094U, shdr[1].sh_size);
- EXPECT_EQ(0U, shdr[1].sh_link);
- EXPECT_EQ(0U, shdr[1].sh_info);
- EXPECT_EQ(0U, shdr[1].sh_addralign);
- EXPECT_EQ(0U, shdr[1].sh_entsize);
-
- EXPECT_EQ(sizeof("\0.text"), shdr[2].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_NOBITS), shdr[2].sh_type);
- EXPECT_EQ(0U, shdr[2].sh_flags);
- EXPECT_EQ(0U, shdr[2].sh_addr);
- EXPECT_EQ(0U, shdr[2].sh_offset);
- EXPECT_EQ(16U, shdr[2].sh_size);
- EXPECT_EQ(0U, shdr[2].sh_link);
- EXPECT_EQ(0U, shdr[2].sh_info);
- EXPECT_EQ(0U, shdr[2].sh_addralign);
- EXPECT_EQ(0U, shdr[2].sh_entsize);
-
- EXPECT_EQ(sizeof("\0.text\0.bss"), shdr[3].sh_name);
- EXPECT_EQ(static_cast<unsigned int>(SHT_STRTAB), shdr[3].sh_type);
- EXPECT_EQ(0U, shdr[3].sh_flags);
- EXPECT_EQ(0U, shdr[3].sh_addr);
- EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr) + 4096, shdr[3].sh_offset);
- EXPECT_EQ(kStringTableSize, shdr[3].sh_size);
- EXPECT_EQ(0U, shdr[3].sh_link);
- EXPECT_EQ(0U, shdr[3].sh_info);
- EXPECT_EQ(0U, shdr[3].sh_addralign);
- EXPECT_EQ(0U, shdr[3].sh_entsize);
-
- const Phdr* phdr =
- reinterpret_cast<const Phdr*>(contents.data() + header->e_phoff);
- EXPECT_EQ(static_cast<unsigned int>(PT_LOAD), phdr->p_type);
- EXPECT_EQ(sizeof(Ehdr) + sizeof(Phdr), phdr->p_offset);
- EXPECT_EQ(0U, phdr->p_vaddr);
- EXPECT_EQ(0U, phdr->p_paddr);
- EXPECT_EQ(4096U, phdr->p_filesz);
- EXPECT_EQ(4096U + 16U, phdr->p_memsz);
- EXPECT_EQ(0U, phdr->p_flags);
- EXPECT_EQ(0U, phdr->p_align);
-}
-
-class ElfNotesTest : public Test {};
-
-TEST_F(ElfNotesTest, Empty) {
- Notes notes(kLittleEndian);
- string contents;
- ASSERT_TRUE(notes.GetContents(&contents));
- EXPECT_EQ(0U, contents.size());
-}
-
-TEST_F(ElfNotesTest, Notes) {
- Notes notes(kLittleEndian);
- notes.AddNote(1, "Linux", reinterpret_cast<const uint8_t *>("\x42\x02\0\0"),
- 4);
- notes.AddNote(2, "a", reinterpret_cast<const uint8_t *>("foobar"),
- sizeof("foobar") - 1);
-
- const uint8_t kExpectedNotesContents[] = {
- // Note 1
- 0x06, 0x00, 0x00, 0x00, // name size, including terminating zero
- 0x04, 0x00, 0x00, 0x00, // desc size
- 0x01, 0x00, 0x00, 0x00, // type
- 'L', 'i', 'n', 'u', 'x', 0x00, 0x00, 0x00, // padded "Linux"
- 0x42, 0x02, 0x00, 0x00, // desc
- // Note 2
- 0x02, 0x00, 0x00, 0x00, // name size
- 0x06, 0x00, 0x00, 0x00, // desc size
- 0x02, 0x00, 0x00, 0x00, // type
- 'a', 0x00, 0x00, 0x00, // padded "a"
- 'f', 'o', 'o', 'b', 'a', 'r', 0x00, 0x00, // padded "foobar"
- };
- const size_t kExpectedNotesSize = sizeof(kExpectedNotesContents);
- EXPECT_EQ(kExpectedNotesSize, notes.Size());
-
- string notes_contents;
- ASSERT_TRUE(notes.GetContents(&notes_contents));
- EXPECT_EQ(0, memcmp(kExpectedNotesContents,
- notes_contents.data(),
- notes_contents.size()));
-}
-
-#endif // defined(__i386__) || defined(__x86_64__)
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h
deleted file mode 100644
index 92fe017b9..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/auto_testfile.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 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.
-
-// Utility class for creating a temporary file for unit tests
-// that is deleted in the destructor.
-
-#ifndef GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
-#define GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/linux/eintr_wrapper.h"
-#include "common/tests/auto_tempdir.h"
-
-namespace google_breakpad {
-
-class AutoTestFile {
- public:
- // Create a new empty test file.
- // test_prefix: (input) test-specific prefix, can't be NULL.
- explicit AutoTestFile(const char* test_prefix) {
- Init(test_prefix);
- }
-
- // Create a new test file, and fill it with initial data from a C string.
- // The terminating zero is not written.
- // test_prefix: (input) test-specific prefix, can't be NULL.
- // text: (input) initial content.
- AutoTestFile(const char* test_prefix, const char* text) {
- Init(test_prefix);
- if (fd_ >= 0)
- WriteText(text, static_cast<size_t>(strlen(text)));
- }
-
- AutoTestFile(const char* test_prefix, const char* text, size_t text_len) {
- Init(test_prefix);
- if (fd_ >= 0)
- WriteText(text, text_len);
- }
-
- // Destroy test file on scope exit.
- ~AutoTestFile() {
- if (fd_ >= 0) {
- close(fd_);
- fd_ = -1;
- }
- }
-
- // Returns true iff the test file could be created properly.
- // Useful in tests inside EXPECT_TRUE(file.IsOk());
- bool IsOk() {
- return fd_ >= 0;
- }
-
- // Returns the Posix file descriptor for the test file, or -1
- // If IsOk() returns false. Note: on Windows, this always returns -1.
- int GetFd() {
- return fd_;
- }
-
- private:
- void Init(const char* test_prefix) {
- fd_ = -1;
- char path_templ[PATH_MAX];
- int ret = snprintf(path_templ, sizeof(path_templ),
- TEMPDIR "/%s-unittest.XXXXXX",
- test_prefix);
- if (ret >= static_cast<int>(sizeof(path_templ)))
- return;
-
- fd_ = mkstemp(path_templ);
- if (fd_ < 0)
- return;
-
- unlink(path_templ);
- }
-
- void WriteText(const char* text, size_t text_len) {
- ssize_t r = HANDLE_EINTR(write(fd_, text, text_len));
- if (r != static_cast<ssize_t>(text_len)) {
- close(fd_);
- fd_ = -1;
- return;
- }
-
- lseek(fd_, 0, SEEK_SET);
- }
-
- int fd_;
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_COMMON_LINUX_TESTS_AUTO_TESTFILE
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc
deleted file mode 100644
index c9491f6f2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.cc
+++ /dev/null
@@ -1,322 +0,0 @@
-// 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.
-
-// crash_generator.cc: Implement google_breakpad::CrashGenerator.
-// See crash_generator.h for details.
-
-#include "common/linux/tests/crash_generator.h"
-
-#include <pthread.h>
-#include <signal.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/resource.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#if defined(__ANDROID__)
-#include "common/android/testing/pthread_fixes.h"
-#endif
-#include "common/linux/eintr_wrapper.h"
-#include "common/tests/auto_tempdir.h"
-#include "common/tests/file_utils.h"
-#include "common/using_std_string.h"
-
-namespace {
-
-struct ThreadData {
- pthread_t thread;
- pthread_barrier_t* barrier;
- pid_t* thread_id_ptr;
-};
-
-const char* const kProcFilesToCopy[] = {
- "auxv", "cmdline", "environ", "maps", "status"
-};
-const size_t kNumProcFilesToCopy =
- sizeof(kProcFilesToCopy) / sizeof(kProcFilesToCopy[0]);
-
-int gettid() {
- // Glibc does not provide a wrapper for this.
- return syscall(__NR_gettid);
-}
-
-int tkill(pid_t tid, int sig) {
- // Glibc does not provide a wrapper for this.
- return syscall(__NR_tkill, tid, sig);
-}
-
-// Core file size limit set to 1 MB, which is big enough for test purposes.
-const rlim_t kCoreSizeLimit = 1024 * 1024;
-
-void *thread_function(void *data) {
- ThreadData* thread_data = reinterpret_cast<ThreadData*>(data);
- volatile pid_t thread_id = gettid();
- *(thread_data->thread_id_ptr) = thread_id;
- int result = pthread_barrier_wait(thread_data->barrier);
- if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) {
- perror("Failed to wait for sync barrier");
- exit(1);
- }
- while (true) {
- pthread_yield();
- }
-}
-
-} // namespace
-
-namespace google_breakpad {
-
-CrashGenerator::CrashGenerator()
- : shared_memory_(NULL),
- shared_memory_size_(0) {
-}
-
-CrashGenerator::~CrashGenerator() {
- UnmapSharedMemory();
-}
-
-bool CrashGenerator::HasDefaultCorePattern() const {
- char buffer[8];
- ssize_t buffer_size = sizeof(buffer);
- return ReadFile("/proc/sys/kernel/core_pattern", buffer, &buffer_size) &&
- buffer_size == 5 && memcmp(buffer, "core", 4) == 0;
-}
-
-string CrashGenerator::GetCoreFilePath() const {
- return temp_dir_.path() + "/core";
-}
-
-string CrashGenerator::GetDirectoryOfProcFilesCopy() const {
- return temp_dir_.path() + "/proc";
-}
-
-pid_t CrashGenerator::GetThreadId(unsigned index) const {
- return reinterpret_cast<pid_t*>(shared_memory_)[index];
-}
-
-pid_t* CrashGenerator::GetThreadIdPointer(unsigned index) {
- return reinterpret_cast<pid_t*>(shared_memory_) + index;
-}
-
-bool CrashGenerator::MapSharedMemory(size_t memory_size) {
- if (!UnmapSharedMemory())
- return false;
-
- void* mapped_memory = mmap(0, memory_size, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_ANONYMOUS, -1, 0);
- if (mapped_memory == MAP_FAILED) {
- perror("CrashGenerator: Failed to map shared memory");
- return false;
- }
-
- memset(mapped_memory, 0, memory_size);
- shared_memory_ = mapped_memory;
- shared_memory_size_ = memory_size;
- return true;
-}
-
-bool CrashGenerator::UnmapSharedMemory() {
- if (!shared_memory_)
- return true;
-
- if (munmap(shared_memory_, shared_memory_size_) == 0) {
- shared_memory_ = NULL;
- shared_memory_size_ = 0;
- return true;
- }
-
- perror("CrashGenerator: Failed to unmap shared memory");
- return false;
-}
-
-bool CrashGenerator::SetCoreFileSizeLimit(rlim_t limit) const {
- struct rlimit limits = { limit, limit };
- if (setrlimit(RLIMIT_CORE, &limits) == -1) {
- perror("CrashGenerator: Failed to set core file size limit");
- return false;
- }
- return true;
-}
-
-bool CrashGenerator::CreateChildCrash(
- unsigned num_threads, unsigned crash_thread, int crash_signal,
- pid_t* child_pid) {
- if (num_threads == 0 || crash_thread >= num_threads) {
- fprintf(stderr, "CrashGenerator: Invalid thread counts; num_threads=%u"
- " crash_thread=%u\n", num_threads, crash_thread);
- return false;
- }
-
- if (!MapSharedMemory(num_threads * sizeof(pid_t))) {
- perror("CrashGenerator: Unable to map shared memory");
- return false;
- }
-
- pid_t pid = fork();
- if (pid == 0) {
- if (chdir(temp_dir_.path().c_str()) == -1) {
- perror("CrashGenerator: Failed to change directory");
- exit(1);
- }
- if (SetCoreFileSizeLimit(kCoreSizeLimit)) {
- CreateThreadsInChildProcess(num_threads);
- string proc_dir = GetDirectoryOfProcFilesCopy();
- if (mkdir(proc_dir.c_str(), 0755) == -1) {
- perror("CrashGenerator: Failed to create proc directory");
- exit(1);
- }
- if (!CopyProcFiles(getpid(), proc_dir.c_str())) {
- fprintf(stderr, "CrashGenerator: Failed to copy proc files\n");
- exit(1);
- }
- // On Android the signal sometimes doesn't seem to get sent even though
- // tkill returns '0'. Retry a couple of times if the signal doesn't get
- // through on the first go:
- // https://code.google.com/p/google-breakpad/issues/detail?id=579
-#if defined(__ANDROID__)
- const int kRetries = 60;
- const unsigned int kSleepTimeInSeconds = 1;
-#else
- const int kRetries = 1;
- const unsigned int kSleepTimeInSeconds = 600;
-#endif
- for (int i = 0; i < kRetries; i++) {
- if (tkill(*GetThreadIdPointer(crash_thread), crash_signal) == -1) {
- perror("CrashGenerator: Failed to kill thread by signal");
- } else {
- // At this point, we've queued the signal for delivery, but there's no
- // guarantee when it'll be delivered. We don't want the main thread to
- // race and exit before the thread we signaled is processed. So sleep
- // long enough that we won't flake even under fairly high load.
- // TODO: See if we can't be a bit more deterministic. There doesn't
- // seem to be an API to check on signal delivery status, so we can't
- // really poll and wait for the kernel to declare the signal has been
- // delivered. If it has, and things worked, we'd be killed, so the
- // sleep length doesn't really matter.
- sleep(kSleepTimeInSeconds);
- }
- }
- } else {
- perror("CrashGenerator: Failed to set core limit");
- }
- exit(1);
- } else if (pid == -1) {
- perror("CrashGenerator: Failed to create child process");
- return false;
- }
-
- int status;
- if (HANDLE_EINTR(waitpid(pid, &status, 0)) == -1) {
- perror("CrashGenerator: Failed to wait for child process");
- return false;
- }
- if (!WIFSIGNALED(status) || WTERMSIG(status) != crash_signal) {
- fprintf(stderr, "CrashGenerator: Child process not killed by the expected signal\n"
- " exit status=0x%x pid=%u signaled=%s sig=%d expected=%d\n",
- status, pid, WIFSIGNALED(status) ? "true" : "false",
- WTERMSIG(status), crash_signal);
- return false;
- }
-
- if (child_pid)
- *child_pid = pid;
- return true;
-}
-
-bool CrashGenerator::CopyProcFiles(pid_t pid, const char* path) const {
- char from_path[PATH_MAX], to_path[PATH_MAX];
- for (size_t i = 0; i < kNumProcFilesToCopy; ++i) {
- int num_chars = snprintf(from_path, PATH_MAX, "/proc/%d/%s",
- pid, kProcFilesToCopy[i]);
- if (num_chars < 0 || num_chars >= PATH_MAX)
- return false;
-
- num_chars = snprintf(to_path, PATH_MAX, "%s/%s",
- path, kProcFilesToCopy[i]);
- if (num_chars < 0 || num_chars >= PATH_MAX)
- return false;
-
- if (!CopyFile(from_path, to_path))
- return false;
- }
- return true;
-}
-
-void CrashGenerator::CreateThreadsInChildProcess(unsigned num_threads) {
- *GetThreadIdPointer(0) = getpid();
-
- if (num_threads <= 1)
- return;
-
- // This method does not clean up any pthread resource, as the process
- // is expected to be killed anyway.
- ThreadData* thread_data = new ThreadData[num_threads];
-
- // Create detached threads so that we do not worry about pthread_join()
- // later being called or not.
- pthread_attr_t thread_attributes;
- if (pthread_attr_init(&thread_attributes) != 0 ||
- pthread_attr_setdetachstate(&thread_attributes,
- PTHREAD_CREATE_DETACHED) != 0) {
- fprintf(stderr, "CrashGenerator: Failed to initialize thread attribute\n");
- exit(1);
- }
-
- pthread_barrier_t thread_barrier;
- if (pthread_barrier_init(&thread_barrier, NULL, num_threads) != 0) {
- fprintf(stderr, "CrashGenerator: Failed to initialize thread barrier\n");
- exit(1);
- }
-
- for (unsigned i = 1; i < num_threads; ++i) {
- thread_data[i].barrier = &thread_barrier;
- thread_data[i].thread_id_ptr = GetThreadIdPointer(i);
- if (pthread_create(&thread_data[i].thread, &thread_attributes,
- thread_function, &thread_data[i]) != 0) {
- fprintf(stderr, "CrashGenerator: Failed to create thread %d\n", i);
- exit(1);
- }
- }
-
- int result = pthread_barrier_wait(&thread_barrier);
- if (result != 0 && result != PTHREAD_BARRIER_SERIAL_THREAD) {
- fprintf(stderr, "CrashGenerator: Failed to wait for thread barrier\n");
- exit(1);
- }
-
- pthread_barrier_destroy(&thread_barrier);
- pthread_attr_destroy(&thread_attributes);
- delete[] thread_data;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h b/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h
deleted file mode 100644
index 7e2fcbf98..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/linux/tests/crash_generator.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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.
-
-// crash_generator.h: Define the google_breakpad::CrashGenerator class,
-// which is used to generate a crash (and a core dump file) for testing.
-
-#ifndef COMMON_LINUX_TESTS_CRASH_GENERATOR_H_
-#define COMMON_LINUX_TESTS_CRASH_GENERATOR_H_
-
-#include <sys/resource.h>
-
-#include <string>
-
-#include "common/tests/auto_tempdir.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-// A utility class for generating a crash (and a core dump file) for
-// testing. It creates a child process with the specified number of
-// threads, which is then termainated by the specified signal. A core
-// dump file is expected to be created upon the termination of the child
-// process, which can then be used for testing code that processes core
-// dump files.
-class CrashGenerator {
- public:
- CrashGenerator();
-
- ~CrashGenerator();
-
- // Returns true if a core dump file named 'core' will be generated in
- // the current directory for a test that produces a crash by checking
- // if /proc/sys/kernel/core_pattern has the default value 'core'.
- bool HasDefaultCorePattern() const;
-
- // Returns the expected path of the core dump file.
- string GetCoreFilePath() const;
-
- // Returns the directory of a copy of proc files of the child process.
- string GetDirectoryOfProcFilesCopy() const;
-
- // Creates a crash (and a core dump file) by creating a child process with
- // |num_threads| threads, and the terminating the child process by sending
- // a signal with number |crash_signal| to the |crash_thread|-th thread.
- // Returns true on success.
- bool CreateChildCrash(unsigned num_threads, unsigned crash_thread,
- int crash_signal, pid_t* child_pid);
-
- // Returns the thread ID of the |index|-th thread in the child process.
- // This method does not validate |index|.
- pid_t GetThreadId(unsigned index) const;
-
- private:
- // Copies the following proc files of the process with |pid| to the directory
- // at |path|: auxv, cmdline, environ, maps, status
- // The directory must have been created. Returns true on success.
- bool CopyProcFiles(pid_t pid, const char* path) const;
-
- // Creates |num_threads| threads in the child process.
- void CreateThreadsInChildProcess(unsigned num_threads);
-
- // Sets the maximum size of core dump file (both the soft and hard limit)
- // to |limit| bytes. Returns true on success.
- bool SetCoreFileSizeLimit(rlim_t limit) const;
-
- // Creates a shared memory of |memory_size| bytes for communicating thread
- // IDs between the parent and child process. Returns true on success.
- bool MapSharedMemory(size_t memory_size);
-
- // Releases any shared memory created by MapSharedMemory(). Returns true on
- // success.
- bool UnmapSharedMemory();
-
- // Returns the pointer to the thread ID of the |index|-th thread in the child
- // process. This method does not validate |index|.
- pid_t* GetThreadIdPointer(unsigned index);
-
- // Temporary directory in which a core file is generated.
- AutoTempDir temp_dir_;
-
- // Shared memory for communicating thread IDs between the parent and
- // child process.
- void* shared_memory_;
-
- // Number of bytes mapped for |shared_memory_|.
- size_t shared_memory_size_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_TESTS_CRASH_GENERATOR_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig
deleted file mode 100644
index f09136908..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/Breakpad.xcconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-GCC_C_LANGUAGE_STANDARD = c99
-
-GCC_WARN_CHECK_SWITCH_STATEMENTS = YES
-// TODO(nealsid): Get the code so we can turn on the 64_TO_32 warning.
-GCC_WARN_64_TO_32_BIT_CONVERSION = NO
-GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
-GCC_WARN_ABOUT_RETURN_TYPE = YES
-GCC_WARN_MISSING_PARENTHESES = YES
-
-// Once https://bugs.chromium.org/p/google-breakpad/issues/detail?id=697
-// is fixed this should be reenabled.
-//GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
-GCC_WARN_ABOUT_MISSING_NEWLINE = YES
-GCC_WARN_SIGN_COMPARE = YES
-GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES
-GCC_WARN_UNDECLARED_SELECTOR = YES
-GCC_WARN_UNKNOWN_PRAGMAS = YES
-GCC_WARN_UNUSED_VARIABLE = YES
-GCC_TREAT_WARNINGS_AS_ERRORS = YES
-
-DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
-
-ALWAYS_SEARCH_USER_PATHS = NO
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig
deleted file mode 100644
index 94cdd8cfc..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadDebug.xcconfig
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 "Breakpad.xcconfig"
-
-GCC_OPTIMIZATION_LEVEL = 0
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig b/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig
deleted file mode 100644
index 920f277db..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/BreakpadRelease.xcconfig
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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 "Breakpad.xcconfig"
-
-GCC_OPTIMIZATION_LEVEL = s
-GCC_WARN_UNINITIALIZED_AUTOS = YES
-GCC_PREPROCESSOR_DEFINITIONS = $(inherited) NDEBUG
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h
deleted file mode 100644
index 14ffa7e13..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMDefines.h
+++ /dev/null
@@ -1,456 +0,0 @@
-//
-// GTMDefines.h
-//
-// Copyright 2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-// ============================================================================
-
-#include <AvailabilityMacros.h>
-#include <TargetConditionals.h>
-
-#ifdef __OBJC__
-#include <Foundation/NSObjCRuntime.h>
-#endif // __OBJC__
-
-#if TARGET_OS_IPHONE
-#include <Availability.h>
-#endif // TARGET_OS_IPHONE
-
-// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
-#ifndef MAC_OS_X_VERSION_10_5
- #define MAC_OS_X_VERSION_10_5 1050
-#endif
-#ifndef MAC_OS_X_VERSION_10_6
- #define MAC_OS_X_VERSION_10_6 1060
-#endif
-#ifndef MAC_OS_X_VERSION_10_7
- #define MAC_OS_X_VERSION_10_7 1070
-#endif
-
-// Not all __IPHONE_X macros defined in past SDKs
-#ifndef __IPHONE_3_0
- #define __IPHONE_3_0 30000
-#endif
-#ifndef __IPHONE_3_1
- #define __IPHONE_3_1 30100
-#endif
-#ifndef __IPHONE_3_2
- #define __IPHONE_3_2 30200
-#endif
-#ifndef __IPHONE_4_0
- #define __IPHONE_4_0 40000
-#endif
-#ifndef __IPHONE_4_3
- #define __IPHONE_4_3 40300
-#endif
-#ifndef __IPHONE_5_0
- #define __IPHONE_5_0 50000
-#endif
-
-// ----------------------------------------------------------------------------
-// CPP symbols that can be overridden in a prefix to control how the toolbox
-// is compiled.
-// ----------------------------------------------------------------------------
-
-
-// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
-// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
-// when a validation fails. If you implement your own validators, you may want
-// to control their internals using the same macros for consistency.
-#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
- #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
-#endif
-
-// Give ourselves a consistent way to do inlines. Apple's macros even use
-// a few different actual definitions, so we're based off of the foundation
-// one.
-#if !defined(GTM_INLINE)
- #if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
- #define GTM_INLINE static __inline__ __attribute__((always_inline))
- #else
- #define GTM_INLINE static __inline__
- #endif
-#endif
-
-// Give ourselves a consistent way of doing externs that links up nicely
-// when mixing objc and objc++
-#if !defined (GTM_EXTERN)
- #if defined __cplusplus
- #define GTM_EXTERN extern "C"
- #define GTM_EXTERN_C_BEGIN extern "C" {
- #define GTM_EXTERN_C_END }
- #else
- #define GTM_EXTERN extern
- #define GTM_EXTERN_C_BEGIN
- #define GTM_EXTERN_C_END
- #endif
-#endif
-
-// Give ourselves a consistent way of exporting things if we have visibility
-// set to hidden.
-#if !defined (GTM_EXPORT)
- #define GTM_EXPORT __attribute__((visibility("default")))
-#endif
-
-// Give ourselves a consistent way of declaring something as unused. This
-// doesn't use __unused because that is only supported in gcc 4.2 and greater.
-#if !defined (GTM_UNUSED)
-#define GTM_UNUSED(x) ((void)(x))
-#endif
-
-// _GTMDevLog & _GTMDevAssert
-//
-// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
-// developer level errors. This implementation simply macros to NSLog/NSAssert.
-// It is not intended to be a general logging/reporting system.
-//
-// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
-// for a little more background on the usage of these macros.
-//
-// _GTMDevLog log some error/problem in debug builds
-// _GTMDevAssert assert if conditon isn't met w/in a method/function
-// in all builds.
-//
-// To replace this system, just provide different macro definitions in your
-// prefix header. Remember, any implementation you provide *must* be thread
-// safe since this could be called by anything in what ever situtation it has
-// been placed in.
-//
-
-// We only define the simple macros if nothing else has defined this.
-#ifndef _GTMDevLog
-
-#ifdef DEBUG
- #define _GTMDevLog(...) NSLog(__VA_ARGS__)
-#else
- #define _GTMDevLog(...) do { } while (0)
-#endif
-
-#endif // _GTMDevLog
-
-#ifndef _GTMDevAssert
-// we directly invoke the NSAssert handler so we can pass on the varargs
-// (NSAssert doesn't have a macro we can use that takes varargs)
-#if !defined(NS_BLOCK_ASSERTIONS)
- #define _GTMDevAssert(condition, ...) \
- do { \
- if (!(condition)) { \
- [[NSAssertionHandler currentHandler] \
- handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
- file:[NSString stringWithUTF8String:__FILE__] \
- lineNumber:__LINE__ \
- description:__VA_ARGS__]; \
- } \
- } while(0)
-#else // !defined(NS_BLOCK_ASSERTIONS)
- #define _GTMDevAssert(condition, ...) do { } while (0)
-#endif // !defined(NS_BLOCK_ASSERTIONS)
-
-#endif // _GTMDevAssert
-
-// _GTMCompileAssert
-// _GTMCompileAssert is an assert that is meant to fire at compile time if you
-// want to check things at compile instead of runtime. For example if you
-// want to check that a wchar is 4 bytes instead of 2 you would use
-// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
-// Note that the second "arg" is not in quotes, and must be a valid processor
-// symbol in it's own right (no spaces, punctuation etc).
-
-// Wrapping this in an #ifndef allows external groups to define their own
-// compile time assert scheme.
-#ifndef _GTMCompileAssert
- // We got this technique from here:
- // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
-
- #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
- #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
- #define _GTMCompileAssert(test, msg) \
- typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
-#endif // _GTMCompileAssert
-
-// ----------------------------------------------------------------------------
-// CPP symbols defined based on the project settings so the GTM code has
-// simple things to test against w/o scattering the knowledge of project
-// setting through all the code.
-// ----------------------------------------------------------------------------
-
-// Provide a single constant CPP symbol that all of GTM uses for ifdefing
-// iPhone code.
-#if TARGET_OS_IPHONE // iPhone SDK
- // For iPhone specific stuff
- #define GTM_IPHONE_SDK 1
- #if TARGET_IPHONE_SIMULATOR
- #define GTM_IPHONE_DEVICE 0
- #define GTM_IPHONE_SIMULATOR 1
- #else
- #define GTM_IPHONE_DEVICE 1
- #define GTM_IPHONE_SIMULATOR 0
- #endif // TARGET_IPHONE_SIMULATOR
- // By default, GTM has provided it's own unittesting support, define this
- // to use the support provided by Xcode, especially for the Xcode4 support
- // for unittesting.
- #ifndef GTM_IPHONE_USE_SENTEST
- #define GTM_IPHONE_USE_SENTEST 0
- #endif
- #define GTM_MACOS_SDK 0
-#else
- // For MacOS specific stuff
- #define GTM_MACOS_SDK 1
- #define GTM_IPHONE_SDK 0
- #define GTM_IPHONE_SIMULATOR 0
- #define GTM_IPHONE_DEVICE 0
- #define GTM_IPHONE_USE_SENTEST 0
-#endif
-
-// Some of our own availability macros
-#if GTM_MACOS_SDK
-#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
-#define GTM_AVAILABLE_ONLY_ON_MACOS
-#else
-#define GTM_AVAILABLE_ONLY_ON_IPHONE
-#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
-#endif
-
-// GC was dropped by Apple, define the old constant incase anyone still keys
-// off of it.
-#ifndef GTM_SUPPORT_GC
- #define GTM_SUPPORT_GC 0
-#endif
-
-// To simplify support for 64bit (and Leopard in general), we provide the type
-// defines for non Leopard SDKs
-#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
- // NSInteger/NSUInteger and Max/Mins
- #ifndef NSINTEGER_DEFINED
- #if (defined(__LP64__) && __LP64__) || NS_BUILD_32_LIKE_64
- typedef long NSInteger;
- typedef unsigned long NSUInteger;
- #else
- typedef int NSInteger;
- typedef unsigned int NSUInteger;
- #endif
- #define NSIntegerMax LONG_MAX
- #define NSIntegerMin LONG_MIN
- #define NSUIntegerMax ULONG_MAX
- #define NSINTEGER_DEFINED 1
- #endif // NSINTEGER_DEFINED
- // CGFloat
- #ifndef CGFLOAT_DEFINED
- #if defined(__LP64__) && __LP64__
- // This really is an untested path (64bit on Tiger?)
- typedef double CGFloat;
- #define CGFLOAT_MIN DBL_MIN
- #define CGFLOAT_MAX DBL_MAX
- #define CGFLOAT_IS_DOUBLE 1
- #else /* !defined(__LP64__) || !__LP64__ */
- typedef float CGFloat;
- #define CGFLOAT_MIN FLT_MIN
- #define CGFLOAT_MAX FLT_MAX
- #define CGFLOAT_IS_DOUBLE 0
- #endif /* !defined(__LP64__) || !__LP64__ */
- #define CGFLOAT_DEFINED 1
- #endif // CGFLOAT_DEFINED
-#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
-
-// Some support for advanced clang static analysis functionality
-// See http://clang-analyzer.llvm.org/annotations.html
-#ifndef __has_feature // Optional.
- #define __has_feature(x) 0 // Compatibility with non-clang compilers.
-#endif
-
-#ifndef NS_RETURNS_RETAINED
- #if __has_feature(attribute_ns_returns_retained)
- #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
- #else
- #define NS_RETURNS_RETAINED
- #endif
-#endif
-
-#ifndef NS_RETURNS_NOT_RETAINED
- #if __has_feature(attribute_ns_returns_not_retained)
- #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
- #else
- #define NS_RETURNS_NOT_RETAINED
- #endif
-#endif
-
-#ifndef CF_RETURNS_RETAINED
- #if __has_feature(attribute_cf_returns_retained)
- #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
- #else
- #define CF_RETURNS_RETAINED
- #endif
-#endif
-
-#ifndef CF_RETURNS_NOT_RETAINED
- #if __has_feature(attribute_cf_returns_not_retained)
- #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
- #else
- #define CF_RETURNS_NOT_RETAINED
- #endif
-#endif
-
-#ifndef NS_CONSUMED
- #if __has_feature(attribute_ns_consumed)
- #define NS_CONSUMED __attribute__((ns_consumed))
- #else
- #define NS_CONSUMED
- #endif
-#endif
-
-#ifndef CF_CONSUMED
- #if __has_feature(attribute_cf_consumed)
- #define CF_CONSUMED __attribute__((cf_consumed))
- #else
- #define CF_CONSUMED
- #endif
-#endif
-
-#ifndef NS_CONSUMES_SELF
- #if __has_feature(attribute_ns_consumes_self)
- #define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
- #else
- #define NS_CONSUMES_SELF
- #endif
-#endif
-
-// Defined on 10.6 and above.
-#ifndef NS_FORMAT_ARGUMENT
- #define NS_FORMAT_ARGUMENT(A)
-#endif
-
-// Defined on 10.6 and above.
-#ifndef NS_FORMAT_FUNCTION
- #define NS_FORMAT_FUNCTION(F,A)
-#endif
-
-// Defined on 10.6 and above.
-#ifndef CF_FORMAT_ARGUMENT
- #define CF_FORMAT_ARGUMENT(A)
-#endif
-
-// Defined on 10.6 and above.
-#ifndef CF_FORMAT_FUNCTION
- #define CF_FORMAT_FUNCTION(F,A)
-#endif
-
-#ifndef GTM_NONNULL
- #if defined(__has_attribute)
- #if __has_attribute(nonnull)
- #define GTM_NONNULL(x) __attribute__((nonnull x))
- #else
- #define GTM_NONNULL(x)
- #endif
- #else
- #define GTM_NONNULL(x)
- #endif
-#endif
-
-// Invalidates the initializer from which it's called.
-#ifndef GTMInvalidateInitializer
- #if __has_feature(objc_arc)
- #define GTMInvalidateInitializer() \
- do { \
- [self class]; /* Avoid warning of dead store to |self|. */ \
- _GTMDevAssert(NO, @"Invalid initializer."); \
- return nil; \
- } while (0)
- #else
- #define GTMInvalidateInitializer() \
- do { \
- [self release]; \
- _GTMDevAssert(NO, @"Invalid initializer."); \
- return nil; \
- } while (0)
- #endif
-#endif
-
-#ifndef GTMCFAutorelease
- #if __has_feature(objc_arc)
- #define GTMCFAutorelease(x) CFBridgingRelease(x)
- #else
- #define GTMCFAutorelease(x) ([(id)x autorelease])
- #endif
-#endif
-
-#ifdef __OBJC__
-
-// Declared here so that it can easily be used for logging tracking if
-// necessary. See GTMUnitTestDevLog.h for details.
-@class NSString;
-GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...) NS_FORMAT_FUNCTION(1, 2);
-
-// Macro to allow you to create NSStrings out of other macros.
-// #define FOO foo
-// NSString *fooString = GTM_NSSTRINGIFY(FOO);
-#if !defined (GTM_NSSTRINGIFY)
- #define GTM_NSSTRINGIFY_INNER(x) @#x
- #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
-#endif
-
-// Macro to allow fast enumeration when building for 10.5 or later, and
-// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
-// does keys, so pick the right thing, nothing is done on the FastEnumeration
-// side to be sure you're getting what you wanted.
-#ifndef GTM_FOREACH_OBJECT
- #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
- #define GTM_FOREACH_ENUMEREE(element, enumeration) \
- for (element in enumeration)
- #define GTM_FOREACH_OBJECT(element, collection) \
- for (element in collection)
- #define GTM_FOREACH_KEY(element, collection) \
- for (element in collection)
- #else
- #define GTM_FOREACH_ENUMEREE(element, enumeration) \
- for (NSEnumerator *_ ## element ## _enum = enumeration; \
- (element = [_ ## element ## _enum nextObject]) != nil; )
- #define GTM_FOREACH_OBJECT(element, collection) \
- GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
- #define GTM_FOREACH_KEY(element, collection) \
- GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
- #endif
-#endif
-
-// ============================================================================
-
-// To simplify support for both Leopard and Snow Leopard we declare
-// the Snow Leopard protocols that we need here.
-#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
-#define GTM_10_6_PROTOCOLS_DEFINED 1
-@protocol NSConnectionDelegate
-@end
-@protocol NSAnimationDelegate
-@end
-@protocol NSImageDelegate
-@end
-@protocol NSTabViewDelegate
-@end
-#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
-
-// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
-// or KVO methods.
-// In debug it will generate warnings for undeclared selectors if
-// -Wunknown-selector is turned on.
-// In release it will have no runtime overhead.
-#ifndef GTM_SEL_STRING
- #ifdef DEBUG
- #define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
- #else
- #define GTM_SEL_STRING(selName) @#selName
- #endif // DEBUG
-#endif // GTM_SEL_STRING
-
-#endif // __OBJC__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h
deleted file mode 100644
index c4fd14029..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.h
+++ /dev/null
@@ -1,504 +0,0 @@
-//
-// GTMLogger.h
-//
-// Copyright 2007-2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-// Key Abstractions
-// ----------------
-//
-// This file declares multiple classes and protocols that are used by the
-// GTMLogger logging system. The 4 main abstractions used in this file are the
-// following:
-//
-// * logger (GTMLogger) - The main logging class that users interact with. It
-// has methods for logging at different levels and uses a log writer, a log
-// formatter, and a log filter to get the job done.
-//
-// * log writer (GTMLogWriter) - Writes a given string to some log file, where
-// a "log file" can be a physical file on disk, a POST over HTTP to some URL,
-// or even some in-memory structure (e.g., a ring buffer).
-//
-// * log formatter (GTMLogFormatter) - Given a format string and arguments as
-// a va_list, returns a single formatted NSString. A "formatted string" could
-// be a string with the date prepended, a string with values in a CSV format,
-// or even a string of XML.
-//
-// * log filter (GTMLogFilter) - Given a formatted log message as an NSString
-// and the level at which the message is to be logged, this class will decide
-// whether the given message should be logged or not. This is a flexible way
-// to filter out messages logged at a certain level, messages that contain
-// certain text, or filter nothing out at all. This gives the caller the
-// flexibility to dynamically enable debug logging in Release builds.
-//
-// This file also declares some classes to handle the common log writer, log
-// formatter, and log filter cases. Callers can also create their own writers,
-// formatters, and filters and they can even build them on top of the ones
-// declared here. Keep in mind that your custom writer/formatter/filter may be
-// called from multiple threads, so it must be thread-safe.
-
-#import <Foundation/Foundation.h>
-#import "GTMDefines.h"
-
-// Predeclaration of used protocols that are declared later in this file.
-@protocol GTMLogWriter, GTMLogFormatter, GTMLogFilter;
-
-// GTMLogger
-//
-// GTMLogger is the primary user-facing class for an object-oriented logging
-// system. It is built on the concept of log formatters (GTMLogFormatter), log
-// writers (GTMLogWriter), and log filters (GTMLogFilter). When a message is
-// sent to a GTMLogger to log a message, the message is formatted using the log
-// formatter, then the log filter is consulted to see if the message should be
-// logged, and if so, the message is sent to the log writer to be written out.
-//
-// GTMLogger is intended to be a flexible and thread-safe logging solution. Its
-// flexibility comes from the fact that GTMLogger instances can be customized
-// with user defined formatters, filters, and writers. And these writers,
-// filters, and formatters can be combined, stacked, and customized in arbitrary
-// ways to suit the needs at hand. For example, multiple writers can be used at
-// the same time, and a GTMLogger instance can even be used as another
-// GTMLogger's writer. This allows for arbitrarily deep logging trees.
-//
-// A standard GTMLogger uses a writer that sends messages to standard out, a
-// formatter that smacks a timestamp and a few other bits of interesting
-// information on the message, and a filter that filters out debug messages from
-// release builds. Using the standard log settings, a log message will look like
-// the following:
-//
-// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] foo=<Foo: 0x123>
-//
-// The output contains the date and time of the log message, the name of the
-// process followed by its process ID/thread ID, the log level at which the
-// message was logged (in the previous example the level was 1:
-// kGTMLoggerLevelDebug), and finally, the user-specified log message itself (in
-// this case, the log message was @"foo=%@", foo).
-//
-// Multiple instances of GTMLogger can be created, each configured their own
-// way. Though GTMLogger is not a singleton (in the GoF sense), it does provide
-// access to a shared (i.e., globally accessible) GTMLogger instance. This makes
-// it convenient for all code in a process to use the same GTMLogger instance.
-// The shared GTMLogger instance can also be configured in an arbitrary, and
-// these configuration changes will affect all code that logs through the shared
-// instance.
-
-//
-// Log Levels
-// ----------
-// GTMLogger has 3 different log levels: Debug, Info, and Error. GTMLogger
-// doesn't take any special action based on the log level; it simply forwards
-// this information on to formatters, filters, and writers, each of which may
-// optionally take action based on the level. Since log level filtering is
-// performed at runtime, log messages are typically not filtered out at compile
-// time. The exception to this rule is that calls to the GTMLoggerDebug() macro
-// *ARE* filtered out of non-DEBUG builds. This is to be backwards compatible
-// with behavior that many developers are currently used to. Note that this
-// means that GTMLoggerDebug(@"hi") will be compiled out of Release builds, but
-// [[GTMLogger sharedLogger] logDebug:@"hi"] will NOT be compiled out.
-//
-// Standard loggers are created with the GTMLogLevelFilter log filter, which
-// filters out certain log messages based on log level, and some other settings.
-//
-// In addition to the -logDebug:, -logInfo:, and -logError: methods defined on
-// GTMLogger itself, there are also C macros that make usage of the shared
-// GTMLogger instance very convenient. These macros are:
-//
-// GTMLoggerDebug(...)
-// GTMLoggerInfo(...)
-// GTMLoggerError(...)
-//
-// Again, a notable feature of these macros is that GTMLogDebug() calls *will be
-// compiled out of non-DEBUG builds*.
-//
-// Standard Loggers
-// ----------------
-// GTMLogger has the concept of "standard loggers". A standard logger is simply
-// a logger that is pre-configured with some standard/common writer, formatter,
-// and filter combination. Standard loggers are created using the creation
-// methods beginning with "standard". The alternative to a standard logger is a
-// regular logger, which will send messages to stdout, with no special
-// formatting, and no filtering.
-//
-// How do I use GTMLogger?
-// ----------------------
-// The typical way you will want to use GTMLogger is to simply use the
-// GTMLogger*() macros for logging from code. That way we can easily make
-// changes to the GTMLogger class and simply update the macros accordingly. Only
-// your application startup code (perhaps, somewhere in main()) should use the
-// GTMLogger class directly in order to configure the shared logger, which all
-// of the code using the macros will be using. Again, this is just the typical
-// situation.
-//
-// To be complete, there are cases where you may want to use GTMLogger directly,
-// or even create separate GTMLogger instances for some reason. That's fine,
-// too.
-//
-// Examples
-// --------
-// The following show some common GTMLogger use cases.
-//
-// 1. You want to log something as simply as possible. Also, this call will only
-// appear in debug builds. In non-DEBUG builds it will be completely removed.
-//
-// GTMLoggerDebug(@"foo = %@", foo);
-//
-// 2. The previous example is similar to the following. The major difference is
-// that the previous call (example 1) will be compiled out of Release builds
-// but this statement will not be compiled out.
-//
-// [[GTMLogger sharedLogger] logDebug:@"foo = %@", foo];
-//
-// 3. Send all logging output from the shared logger to a file. We do this by
-// creating an NSFileHandle for writing associated with a file, and setting
-// that file handle as the logger's writer.
-//
-// NSFileHandle *f = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log"
-// create:YES];
-// [[GTMLogger sharedLogger] setWriter:f];
-// GTMLoggerError(@"hi"); // This will be sent to /tmp/f.log
-//
-// 4. Create a new GTMLogger that will log to a file. This example differs from
-// the previous one because here we create a new GTMLogger that is different
-// from the shared logger.
-//
-// GTMLogger *logger = [GTMLogger standardLoggerWithPath:@"/tmp/temp.log"];
-// [logger logInfo:@"hi temp log file"];
-//
-// 5. Create a logger that writes to stdout and does NOT do any formatting to
-// the log message. This might be useful, for example, when writing a help
-// screen for a command-line tool to standard output.
-//
-// GTMLogger *logger = [GTMLogger logger];
-// [logger logInfo:@"%@ version 0.1 usage", progName];
-//
-// 6. Send log output to stdout AND to a log file. The trick here is that
-// NSArrays function as composite log writers, which means when an array is
-// set as the log writer, it forwards all logging messages to all of its
-// contained GTMLogWriters.
-//
-// // Create array of GTMLogWriters
-// NSArray *writers = [NSArray arrayWithObjects:
-// [NSFileHandle fileHandleForWritingAtPath:@"/tmp/f.log" create:YES],
-// [NSFileHandle fileHandleWithStandardOutput], nil];
-//
-// GTMLogger *logger = [GTMLogger standardLogger];
-// [logger setWriter:writers];
-// [logger logInfo:@"hi"]; // Output goes to stdout and /tmp/f.log
-//
-// For futher details on log writers, formatters, and filters, see the
-// documentation below.
-//
-// NOTE: GTMLogger is application level logging. By default it does nothing
-// with _GTMDevLog/_GTMDevAssert (see GTMDefines.h). An application can choose
-// to bridge _GTMDevLog/_GTMDevAssert to GTMLogger by providing macro
-// definitions in its prefix header (see GTMDefines.h for how one would do
-// that).
-//
-@interface GTMLogger : NSObject {
- @private
- id<GTMLogWriter> writer_;
- id<GTMLogFormatter> formatter_;
- id<GTMLogFilter> filter_;
-}
-
-//
-// Accessors for the shared logger instance
-//
-
-// Returns a shared/global standard GTMLogger instance. Callers should typically
-// use this method to get a GTMLogger instance, unless they explicitly want
-// their own instance to configure for their own needs. This is the only method
-// that returns a shared instance; all the rest return new GTMLogger instances.
-+ (id)sharedLogger;
-
-// Sets the shared logger instance to |logger|. Future calls to +sharedLogger
-// will return |logger| instead.
-+ (void)setSharedLogger:(GTMLogger *)logger;
-
-//
-// Creation methods
-//
-
-// Returns a new autoreleased GTMLogger instance that will log to stdout, using
-// the GTMLogStandardFormatter, and the GTMLogLevelFilter filter.
-+ (id)standardLogger;
-
-// Same as +standardLogger, but logs to stderr.
-+ (id)standardLoggerWithStderr;
-
-// Same as +standardLogger but levels >= kGTMLoggerLevelError are routed to
-// stderr, everything else goes to stdout.
-+ (id)standardLoggerWithStdoutAndStderr;
-
-// Returns a new standard GTMLogger instance with a log writer that will
-// write to the file at |path|, and will use the GTMLogStandardFormatter and
-// GTMLogLevelFilter classes. If |path| does not exist, it will be created.
-+ (id)standardLoggerWithPath:(NSString *)path;
-
-// Returns an autoreleased GTMLogger instance that will use the specified
-// |writer|, |formatter|, and |filter|.
-+ (id)loggerWithWriter:(id<GTMLogWriter>)writer
- formatter:(id<GTMLogFormatter>)formatter
- filter:(id<GTMLogFilter>)filter;
-
-// Returns an autoreleased GTMLogger instance that logs to stdout, with the
-// basic formatter, and no filter. The returned logger differs from the logger
-// returned by +standardLogger because this one does not do any filtering and
-// does not do any special log formatting; this is the difference between a
-// "regular" logger and a "standard" logger.
-+ (id)logger;
-
-// Designated initializer. This method returns a GTMLogger initialized with the
-// specified |writer|, |formatter|, and |filter|. See the setter methods below
-// for what values will be used if nil is passed for a parameter.
-- (id)initWithWriter:(id<GTMLogWriter>)writer
- formatter:(id<GTMLogFormatter>)formatter
- filter:(id<GTMLogFilter>)filter;
-
-//
-// Logging methods
-//
-
-// Logs a message at the debug level (kGTMLoggerLevelDebug).
-- (void)logDebug:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
-// Logs a message at the info level (kGTMLoggerLevelInfo).
-- (void)logInfo:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
-// Logs a message at the error level (kGTMLoggerLevelError).
-- (void)logError:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
-// Logs a message at the assert level (kGTMLoggerLevelAssert).
-- (void)logAssert:(NSString *)fmt, ... NS_FORMAT_FUNCTION(1, 2);
-
-
-//
-// Accessors
-//
-
-// Accessor methods for the log writer. If the log writer is set to nil,
-// [NSFileHandle fileHandleWithStandardOutput] is used.
-- (id<GTMLogWriter>)writer;
-- (void)setWriter:(id<GTMLogWriter>)writer;
-
-// Accessor methods for the log formatter. If the log formatter is set to nil,
-// GTMLogBasicFormatter is used. This formatter will format log messages in a
-// plain printf style.
-- (id<GTMLogFormatter>)formatter;
-- (void)setFormatter:(id<GTMLogFormatter>)formatter;
-
-// Accessor methods for the log filter. If the log filter is set to nil,
-// GTMLogNoFilter is used, which allows all log messages through.
-- (id<GTMLogFilter>)filter;
-- (void)setFilter:(id<GTMLogFilter>)filter;
-
-@end // GTMLogger
-
-
-// Helper functions that are used by the convenience GTMLogger*() macros that
-// enable the logging of function names.
-@interface GTMLogger (GTMLoggerMacroHelpers)
-- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ...
- NS_FORMAT_FUNCTION(2, 3);
-- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ...
- NS_FORMAT_FUNCTION(2, 3);
-- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ...
- NS_FORMAT_FUNCTION(2, 3);
-- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ...
- NS_FORMAT_FUNCTION(2, 3);
-@end // GTMLoggerMacroHelpers
-
-
-// The convenience macros are only defined if they haven't already been defined.
-#ifndef GTMLoggerInfo
-
-// Convenience macros that log to the shared GTMLogger instance. These macros
-// are how users should typically log to GTMLogger. Notice that GTMLoggerDebug()
-// calls will be compiled out of non-Debug builds.
-#define GTMLoggerDebug(...) \
- [[GTMLogger sharedLogger] logFuncDebug:__func__ msg:__VA_ARGS__]
-#define GTMLoggerInfo(...) \
- [[GTMLogger sharedLogger] logFuncInfo:__func__ msg:__VA_ARGS__]
-#define GTMLoggerError(...) \
- [[GTMLogger sharedLogger] logFuncError:__func__ msg:__VA_ARGS__]
-#define GTMLoggerAssert(...) \
- [[GTMLogger sharedLogger] logFuncAssert:__func__ msg:__VA_ARGS__]
-
-// If we're not in a debug build, remove the GTMLoggerDebug statements. This
-// makes calls to GTMLoggerDebug "compile out" of Release builds
-#ifndef DEBUG
-#undef GTMLoggerDebug
-#define GTMLoggerDebug(...) do {} while(0)
-#endif
-
-#endif // !defined(GTMLoggerInfo)
-
-// Log levels.
-typedef enum {
- kGTMLoggerLevelUnknown,
- kGTMLoggerLevelDebug,
- kGTMLoggerLevelInfo,
- kGTMLoggerLevelError,
- kGTMLoggerLevelAssert,
-} GTMLoggerLevel;
-
-
-//
-// Log Writers
-//
-
-// Protocol to be implemented by a GTMLogWriter instance.
-@protocol GTMLogWriter <NSObject>
-// Writes the given log message to where the log writer is configured to write.
-- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level;
-@end // GTMLogWriter
-
-
-// Simple category on NSFileHandle that makes NSFileHandles valid log writers.
-// This is convenient because something like, say, +fileHandleWithStandardError
-// now becomes a valid log writer. Log messages are written to the file handle
-// with a newline appended.
-@interface NSFileHandle (GTMFileHandleLogWriter) <GTMLogWriter>
-// Opens the file at |path| in append mode, and creates the file with |mode|
-// if it didn't previously exist.
-+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode;
-@end // NSFileHandle
-
-
-// This category makes NSArray a GTMLogWriter that can be composed of other
-// GTMLogWriters. This is the classic Composite GoF design pattern. When the
-// GTMLogWriter -logMessage:level: message is sent to the array, the array
-// forwards the message to all of its elements that implement the GTMLogWriter
-// protocol.
-//
-// This is useful in situations where you would like to send log output to
-// multiple log writers at the same time. Simply create an NSArray of the log
-// writers you wish to use, then set the array as the "writer" for your
-// GTMLogger instance.
-@interface NSArray (GTMArrayCompositeLogWriter) <GTMLogWriter>
-@end // GTMArrayCompositeLogWriter
-
-
-// This category adapts the GTMLogger interface so that it can be used as a log
-// writer; it's an "adapter" in the GoF Adapter pattern sense.
-//
-// This is useful when you want to configure a logger to log to a specific
-// writer with a specific formatter and/or filter. But you want to also compose
-// that with a different log writer that may have its own formatter and/or
-// filter.
-@interface GTMLogger (GTMLoggerLogWriter) <GTMLogWriter>
-@end // GTMLoggerLogWriter
-
-
-//
-// Log Formatters
-//
-
-// Protocol to be implemented by a GTMLogFormatter instance.
-@protocol GTMLogFormatter <NSObject>
-// Returns a formatted string using the format specified in |fmt| and the va
-// args specified in |args|.
-- (NSString *)stringForFunc:(NSString *)func
- withFormat:(NSString *)fmt
- valist:(va_list)args
- level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
-@end // GTMLogFormatter
-
-
-// A basic log formatter that formats a string the same way that NSLog (or
-// printf) would. It does not do anything fancy, nor does it add any data of its
-// own.
-@interface GTMLogBasicFormatter : NSObject <GTMLogFormatter>
-
-// Helper method for prettying C99 __func__ and GCC __PRETTY_FUNCTION__
-- (NSString *)prettyNameForFunc:(NSString *)func;
-
-@end // GTMLogBasicFormatter
-
-
-// A log formatter that formats the log string like the basic formatter, but
-// also prepends a timestamp and some basic process info to the message, as
-// shown in the following sample output.
-// 2007-12-30 10:29:24.177 myapp[4588/0xa07d0f60] [lvl=1] log mesage here
-@interface GTMLogStandardFormatter : GTMLogBasicFormatter {
- @private
- NSDateFormatter *dateFormatter_; // yyyy-MM-dd HH:mm:ss.SSS
- NSString *pname_;
- pid_t pid_;
-}
-@end // GTMLogStandardFormatter
-
-
-//
-// Log Filters
-//
-
-// Protocol to be imlemented by a GTMLogFilter instance.
-@protocol GTMLogFilter <NSObject>
-// Returns YES if |msg| at |level| should be filtered out; NO otherwise.
-- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level;
-@end // GTMLogFilter
-
-
-// A log filter that filters messages at the kGTMLoggerLevelDebug level out of
-// non-debug builds. Messages at the kGTMLoggerLevelInfo level are also filtered
-// out of non-debug builds unless GTMVerboseLogging is set in the environment or
-// the processes's defaults. Messages at the kGTMLoggerLevelError level are
-// never filtered.
-@interface GTMLogLevelFilter : NSObject <GTMLogFilter>
-@end // GTMLogLevelFilter
-
-// A simple log filter that does NOT filter anything out;
-// -filterAllowsMessage:level will always return YES. This can be a convenient
-// way to enable debug-level logging in release builds (if you so desire).
-@interface GTMLogNoFilter : NSObject <GTMLogFilter>
-@end // GTMLogNoFilter
-
-
-// Base class for custom level filters. Not for direct use, use the minimum
-// or maximum level subclasses below.
-@interface GTMLogAllowedLevelFilter : NSObject <GTMLogFilter> {
- @private
- NSIndexSet *allowedLevels_;
-}
-@end
-
-// A log filter that allows you to set a minimum log level. Messages below this
-// level will be filtered.
-@interface GTMLogMininumLevelFilter : GTMLogAllowedLevelFilter
-
-// Designated initializer, logs at levels < |level| will be filtered.
-- (id)initWithMinimumLevel:(GTMLoggerLevel)level;
-
-@end
-
-// A log filter that allows you to set a maximum log level. Messages whose level
-// exceeds this level will be filtered. This is really only useful if you have
-// a composite GTMLogger that is sending the other messages elsewhere.
-@interface GTMLogMaximumLevelFilter : GTMLogAllowedLevelFilter
-
-// Designated initializer, logs at levels > |level| will be filtered.
-- (id)initWithMaximumLevel:(GTMLoggerLevel)level;
-
-@end
-
-
-// For subclasses only
-@interface GTMLogger (PrivateMethods)
-
-- (void)logInternalFunc:(const char *)func
- format:(NSString *)fmt
- valist:(va_list)args
- level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0);
-
-@end
-
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m b/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m
deleted file mode 100644
index ebc5836a2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/GTMLogger.m
+++ /dev/null
@@ -1,611 +0,0 @@
-//
-// GTMLogger.m
-//
-// Copyright 2007-2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-#import "GTMLogger.h"
-#import <fcntl.h>
-#import <unistd.h>
-#import <stdlib.h>
-#import <pthread.h>
-
-
-#if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42)
-// Some versions of GCC (4.2 and below AFAIK) aren't great about supporting
-// -Wmissing-format-attribute
-// when the function is anything more complex than foo(NSString *fmt, ...).
-// You see the error inside the function when you turn ... into va_args and
-// attempt to call another function (like vsprintf for example).
-// So we just shut off the warning for this file. We reenable it at the end.
-#pragma GCC diagnostic ignored "-Wmissing-format-attribute"
-#endif // !__clang__
-
-// Reference to the shared GTMLogger instance. This is not a singleton, it's
-// just an easy reference to one shared instance.
-static GTMLogger *gSharedLogger = nil;
-
-
-@implementation GTMLogger
-
-// Returns a pointer to the shared logger instance. If none exists, a standard
-// logger is created and returned.
-+ (id)sharedLogger {
- @synchronized(self) {
- if (gSharedLogger == nil) {
- gSharedLogger = [[self standardLogger] retain];
- }
- }
- return [[gSharedLogger retain] autorelease];
-}
-
-+ (void)setSharedLogger:(GTMLogger *)logger {
- @synchronized(self) {
- [gSharedLogger autorelease];
- gSharedLogger = [logger retain];
- }
-}
-
-+ (id)standardLogger {
- // Don't trust NSFileHandle not to throw
- @try {
- id<GTMLogWriter> writer = [NSFileHandle fileHandleWithStandardOutput];
- id<GTMLogFormatter> fr = [[[GTMLogStandardFormatter alloc] init]
- autorelease];
- id<GTMLogFilter> filter = [[[GTMLogLevelFilter alloc] init] autorelease];
- return [[[self alloc] initWithWriter:writer
- formatter:fr
- filter:filter] autorelease];
- }
- @catch (id e) {
- // Ignored
- }
- return nil;
-}
-
-+ (id)standardLoggerWithStderr {
- // Don't trust NSFileHandle not to throw
- @try {
- id me = [self standardLogger];
- [me setWriter:[NSFileHandle fileHandleWithStandardError]];
- return me;
- }
- @catch (id e) {
- // Ignored
- }
- return nil;
-}
-
-+ (id)standardLoggerWithStdoutAndStderr {
- // We're going to take advantage of the GTMLogger to GTMLogWriter adaptor
- // and create a composite logger that an outer "standard" logger can use
- // as a writer. Our inner loggers should apply no formatting since the main
- // logger does that and we want the caller to be able to change formatters
- // or add writers without knowing the inner structure of our composite.
-
- // Don't trust NSFileHandle not to throw
- @try {
- GTMLogBasicFormatter *formatter = [[[GTMLogBasicFormatter alloc] init]
- autorelease];
- GTMLogger *stdoutLogger =
- [self loggerWithWriter:[NSFileHandle fileHandleWithStandardOutput]
- formatter:formatter
- filter:[[[GTMLogMaximumLevelFilter alloc]
- initWithMaximumLevel:kGTMLoggerLevelInfo]
- autorelease]];
- GTMLogger *stderrLogger =
- [self loggerWithWriter:[NSFileHandle fileHandleWithStandardError]
- formatter:formatter
- filter:[[[GTMLogMininumLevelFilter alloc]
- initWithMinimumLevel:kGTMLoggerLevelError]
- autorelease]];
- GTMLogger *compositeWriter =
- [self loggerWithWriter:[NSArray arrayWithObjects:
- stdoutLogger, stderrLogger, nil]
- formatter:formatter
- filter:[[[GTMLogNoFilter alloc] init] autorelease]];
- GTMLogger *outerLogger = [self standardLogger];
- [outerLogger setWriter:compositeWriter];
- return outerLogger;
- }
- @catch (id e) {
- // Ignored
- }
- return nil;
-}
-
-+ (id)standardLoggerWithPath:(NSString *)path {
- @try {
- NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644];
- if (fh == nil) return nil;
- id me = [self standardLogger];
- [me setWriter:fh];
- return me;
- }
- @catch (id e) {
- // Ignored
- }
- return nil;
-}
-
-+ (id)loggerWithWriter:(id<GTMLogWriter>)writer
- formatter:(id<GTMLogFormatter>)formatter
- filter:(id<GTMLogFilter>)filter {
- return [[[self alloc] initWithWriter:writer
- formatter:formatter
- filter:filter] autorelease];
-}
-
-+ (id)logger {
- return [[[self alloc] init] autorelease];
-}
-
-- (id)init {
- return [self initWithWriter:nil formatter:nil filter:nil];
-}
-
-- (id)initWithWriter:(id<GTMLogWriter>)writer
- formatter:(id<GTMLogFormatter>)formatter
- filter:(id<GTMLogFilter>)filter {
- if ((self = [super init])) {
- [self setWriter:writer];
- [self setFormatter:formatter];
- [self setFilter:filter];
- }
- return self;
-}
-
-- (void)dealloc {
- // Unlikely, but |writer_| may be an NSFileHandle, which can throw
- @try {
- [formatter_ release];
- [filter_ release];
- [writer_ release];
- }
- @catch (id e) {
- // Ignored
- }
- [super dealloc];
-}
-
-- (id<GTMLogWriter>)writer {
- return [[writer_ retain] autorelease];
-}
-
-- (void)setWriter:(id<GTMLogWriter>)writer {
- @synchronized(self) {
- [writer_ autorelease];
- writer_ = nil;
- if (writer == nil) {
- // Try to use stdout, but don't trust NSFileHandle
- @try {
- writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain];
- }
- @catch (id e) {
- // Leave |writer_| nil
- }
- } else {
- writer_ = [writer retain];
- }
- }
-}
-
-- (id<GTMLogFormatter>)formatter {
- return [[formatter_ retain] autorelease];
-}
-
-- (void)setFormatter:(id<GTMLogFormatter>)formatter {
- @synchronized(self) {
- [formatter_ autorelease];
- formatter_ = nil;
- if (formatter == nil) {
- @try {
- formatter_ = [[GTMLogBasicFormatter alloc] init];
- }
- @catch (id e) {
- // Leave |formatter_| nil
- }
- } else {
- formatter_ = [formatter retain];
- }
- }
-}
-
-- (id<GTMLogFilter>)filter {
- return [[filter_ retain] autorelease];
-}
-
-- (void)setFilter:(id<GTMLogFilter>)filter {
- @synchronized(self) {
- [filter_ autorelease];
- filter_ = nil;
- if (filter == nil) {
- @try {
- filter_ = [[GTMLogNoFilter alloc] init];
- }
- @catch (id e) {
- // Leave |filter_| nil
- }
- } else {
- filter_ = [filter retain];
- }
- }
-}
-
-- (void)logDebug:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug];
- va_end(args);
-}
-
-- (void)logInfo:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo];
- va_end(args);
-}
-
-- (void)logError:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError];
- va_end(args);
-}
-
-- (void)logAssert:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert];
- va_end(args);
-}
-
-@end // GTMLogger
-
-@implementation GTMLogger (GTMLoggerMacroHelpers)
-
-- (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug];
- va_end(args);
-}
-
-- (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo];
- va_end(args);
-}
-
-- (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError];
- va_end(args);
-}
-
-- (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... {
- va_list args;
- va_start(args, fmt);
- [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert];
- va_end(args);
-}
-
-@end // GTMLoggerMacroHelpers
-
-@implementation GTMLogger (PrivateMethods)
-
-- (void)logInternalFunc:(const char *)func
- format:(NSString *)fmt
- valist:(va_list)args
- level:(GTMLoggerLevel)level {
- // Primary point where logging happens, logging should never throw, catch
- // everything.
- @try {
- NSString *fname = func ? [NSString stringWithUTF8String:func] : nil;
- NSString *msg = [formatter_ stringForFunc:fname
- withFormat:fmt
- valist:args
- level:level];
- if (msg && [filter_ filterAllowsMessage:msg level:level])
- [writer_ logMessage:msg level:level];
- }
- @catch (id e) {
- // Ignored
- }
-}
-
-@end // PrivateMethods
-
-
-@implementation NSFileHandle (GTMFileHandleLogWriter)
-
-+ (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode {
- int fd = -1;
- if (path) {
- int flags = O_WRONLY | O_APPEND | O_CREAT;
- fd = open([path fileSystemRepresentation], flags, mode);
- }
- if (fd == -1) return nil;
- return [[[self alloc] initWithFileDescriptor:fd
- closeOnDealloc:YES] autorelease];
-}
-
-- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
- @synchronized(self) {
- // Closed pipes should not generate exceptions in our caller. Catch here
- // as well [GTMLogger logInternalFunc:...] so that an exception in this
- // writer does not prevent other writers from having a chance.
- @try {
- NSString *line = [NSString stringWithFormat:@"%@\n", msg];
- [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]];
- }
- @catch (id e) {
- // Ignored
- }
- }
-}
-
-@end // GTMFileHandleLogWriter
-
-
-@implementation NSArray (GTMArrayCompositeLogWriter)
-
-- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
- @synchronized(self) {
- id<GTMLogWriter> child = nil;
- GTM_FOREACH_OBJECT(child, self) {
- if ([child conformsToProtocol:@protocol(GTMLogWriter)])
- [child logMessage:msg level:level];
- }
- }
-}
-
-@end // GTMArrayCompositeLogWriter
-
-
-@implementation GTMLogger (GTMLoggerLogWriter)
-
-- (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level {
- switch (level) {
- case kGTMLoggerLevelDebug:
- [self logDebug:@"%@", msg];
- break;
- case kGTMLoggerLevelInfo:
- [self logInfo:@"%@", msg];
- break;
- case kGTMLoggerLevelError:
- [self logError:@"%@", msg];
- break;
- case kGTMLoggerLevelAssert:
- [self logAssert:@"%@", msg];
- break;
- default:
- // Ignore the message.
- break;
- }
-}
-
-@end // GTMLoggerLogWriter
-
-
-@implementation GTMLogBasicFormatter
-
-- (NSString *)prettyNameForFunc:(NSString *)func {
- NSString *name = [func stringByTrimmingCharactersInSet:
- [NSCharacterSet whitespaceAndNewlineCharacterSet]];
- NSString *function = @"(unknown)";
- if ([name length]) {
- if (// Objective C __func__ and __PRETTY_FUNCTION__
- [name hasPrefix:@"-["] || [name hasPrefix:@"+["] ||
- // C++ __PRETTY_FUNCTION__ and other preadorned formats
- [name hasSuffix:@")"]) {
- function = name;
- } else {
- // Assume C99 __func__
- function = [NSString stringWithFormat:@"%@()", name];
- }
- }
- return function;
-}
-
-- (NSString *)stringForFunc:(NSString *)func
- withFormat:(NSString *)fmt
- valist:(va_list)args
- level:(GTMLoggerLevel)level {
- // Performance note: We may want to do a quick check here to see if |fmt|
- // contains a '%', and if not, simply return 'fmt'.
- if (!(fmt && args)) return nil;
- return [[[NSString alloc] initWithFormat:fmt arguments:args] autorelease];
-}
-
-@end // GTMLogBasicFormatter
-
-
-@implementation GTMLogStandardFormatter
-
-- (id)init {
- if ((self = [super init])) {
- dateFormatter_ = [[NSDateFormatter alloc] init];
- [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4];
- [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"];
- pname_ = [[[NSProcessInfo processInfo] processName] copy];
- pid_ = [[NSProcessInfo processInfo] processIdentifier];
- if (!(dateFormatter_ && pname_)) {
- [self release];
- return nil;
- }
- }
- return self;
-}
-
-- (void)dealloc {
- [dateFormatter_ release];
- [pname_ release];
- [super dealloc];
-}
-
-- (NSString *)stringForFunc:(NSString *)func
- withFormat:(NSString *)fmt
- valist:(va_list)args
- level:(GTMLoggerLevel)level {
- NSString *tstamp = nil;
- @synchronized (dateFormatter_) {
- tstamp = [dateFormatter_ stringFromDate:[NSDate date]];
- }
- return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@",
- tstamp, pname_, pid_, pthread_self(),
- level, [self prettyNameForFunc:func],
- // |super| has guard for nil |fmt| and |args|
- [super stringForFunc:func withFormat:fmt valist:args level:level]];
-}
-
-@end // GTMLogStandardFormatter
-
-
-@implementation GTMLogLevelFilter
-
-// Check the environment and the user preferences for the GTMVerboseLogging key
-// to see if verbose logging has been enabled. The environment variable will
-// override the defaults setting, so check the environment first.
-// COV_NF_START
-static BOOL IsVerboseLoggingEnabled(void) {
- static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging";
- NSString *value = [[[NSProcessInfo processInfo] environment]
- objectForKey:kVerboseLoggingKey];
- if (value) {
- // Emulate [NSString boolValue] for pre-10.5
- value = [value stringByTrimmingCharactersInSet:
- [NSCharacterSet whitespaceAndNewlineCharacterSet]];
- if ([[value uppercaseString] hasPrefix:@"Y"] ||
- [[value uppercaseString] hasPrefix:@"T"] ||
- [value intValue]) {
- return YES;
- } else {
- return NO;
- }
- }
- return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey];
-}
-// COV_NF_END
-
-// In DEBUG builds, log everything. If we're not in a debug build we'll assume
-// that we're in a Release build.
-- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
-#if defined(DEBUG) && DEBUG
- return YES;
-#endif
-
- BOOL allow = YES;
-
- switch (level) {
- case kGTMLoggerLevelDebug:
- allow = NO;
- break;
- case kGTMLoggerLevelInfo:
- allow = IsVerboseLoggingEnabled();
- break;
- case kGTMLoggerLevelError:
- allow = YES;
- break;
- case kGTMLoggerLevelAssert:
- allow = YES;
- break;
- default:
- allow = YES;
- break;
- }
-
- return allow;
-}
-
-@end // GTMLogLevelFilter
-
-
-@implementation GTMLogNoFilter
-
-- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
- return YES; // Allow everything through
-}
-
-@end // GTMLogNoFilter
-
-
-@implementation GTMLogAllowedLevelFilter
-
-// Private designated initializer
-- (id)initWithAllowedLevels:(NSIndexSet *)levels {
- self = [super init];
- if (self != nil) {
- allowedLevels_ = [levels retain];
- // Cap min/max level
- if (!allowedLevels_ ||
- // NSIndexSet is unsigned so only check the high bound, but need to
- // check both first and last index because NSIndexSet appears to allow
- // wraparound.
- ([allowedLevels_ firstIndex] > kGTMLoggerLevelAssert) ||
- ([allowedLevels_ lastIndex] > kGTMLoggerLevelAssert)) {
- [self release];
- return nil;
- }
- }
- return self;
-}
-
-- (id)init {
- // Allow all levels in default init
- return [self initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
- NSMakeRange(kGTMLoggerLevelUnknown,
- (kGTMLoggerLevelAssert - kGTMLoggerLevelUnknown + 1))]];
-}
-
-- (void)dealloc {
- [allowedLevels_ release];
- [super dealloc];
-}
-
-- (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level {
- return [allowedLevels_ containsIndex:level];
-}
-
-@end // GTMLogAllowedLevelFilter
-
-
-@implementation GTMLogMininumLevelFilter
-
-- (id)initWithMinimumLevel:(GTMLoggerLevel)level {
- return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
- NSMakeRange(level,
- (kGTMLoggerLevelAssert - level + 1))]];
-}
-
-@end // GTMLogMininumLevelFilter
-
-
-@implementation GTMLogMaximumLevelFilter
-
-- (id)initWithMaximumLevel:(GTMLoggerLevel)level {
- return [super initWithAllowedLevels:[NSIndexSet indexSetWithIndexesInRange:
- NSMakeRange(kGTMLoggerLevelUnknown, level + 1)]];
-}
-
-@end // GTMLogMaximumLevelFilter
-
-#if !defined(__clang__) && (__GNUC__*10+__GNUC_MINOR__ >= 42)
-// See comment at top of file.
-#pragma GCC diagnostic error "-Wmissing-format-attribute"
-#endif // !__clang__
-
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h
deleted file mode 100644
index 42e8fed39..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// HTTPMultipartUpload: A multipart/form-data HTTP uploader.
-// Each parameter pair is sent as a boundary
-// Each file is sent with a name field in addition to the filename and data
-// The data will be sent synchronously.
-
-#import <Foundation/Foundation.h>
-
-@interface HTTPMultipartUpload : NSObject {
- @protected
- NSURL *url_; // The destination URL (STRONG)
- NSDictionary *parameters_; // The key/value pairs for sending data (STRONG)
- NSMutableDictionary *files_; // Dictionary of name/file-path (STRONG)
- NSString *boundary_; // The boundary string (STRONG)
- NSHTTPURLResponse *response_; // The response from the send (STRONG)
-}
-
-- (id)initWithURL:(NSURL *)url;
-
-- (NSURL *)URL;
-
-- (void)setParameters:(NSDictionary *)parameters;
-- (NSDictionary *)parameters;
-
-- (void)addFileAtPath:(NSString *)path name:(NSString *)name;
-- (void)addFileContents:(NSData *)data name:(NSString *)name;
-- (NSDictionary *)files;
-
-// Set the data and return the response
-- (NSData *)send:(NSError **)error;
-- (NSHTTPURLResponse *)response;
-
-@end
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m b/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m
deleted file mode 100644
index 9ac886d53..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/HTTPMultipartUpload.m
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#import "HTTPMultipartUpload.h"
-#import "GTMDefines.h"
-
-// As -[NSString stringByAddingPercentEscapesUsingEncoding:] has been
-// deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements it
-// using -[NSString stringByAddingPercentEncodingWithAllowedCharacters:] when
-// using those SDKs.
-static NSString *PercentEncodeNSString(NSString *key) {
-#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \
- __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \
- (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
- defined(MAC_OS_X_VERSION_10_11) && \
- MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11)
- return [key stringByAddingPercentEncodingWithAllowedCharacters:
- [NSCharacterSet URLQueryAllowedCharacterSet]];
-#else
- return [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-#endif
-}
-
-// As -[NSURLConnection sendSynchronousRequest:returningResponse:error:] has
-// been deprecated with iOS 9.0 / OS X 10.11 SDKs, this function re-implements
-// it using -[NSURLSession dataTaskWithRequest:completionHandler:] when using
-// those SDKs.
-static NSData *SendSynchronousNSURLRequest(NSURLRequest *req,
- NSURLResponse **out_response,
- NSError **out_error) {
-#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_9_0) && \
- __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0) || \
- (defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \
- defined(MAC_OS_X_VERSION_10_11) && \
- MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_11)
- __block NSData* result = nil;
- __block NSError* error = nil;
- __block NSURLResponse* response = nil;
- dispatch_semaphore_t wait_semaphone = dispatch_semaphore_create(0);
- [[[NSURLSession sharedSession]
- dataTaskWithRequest:req
- completionHandler:^(NSData *data,
- NSURLResponse *resp,
- NSError *err) {
- if (out_error)
- error = [err retain];
- if (out_response)
- response = [resp retain];
- if (err == nil)
- result = [data retain];
- dispatch_semaphore_signal(wait_semaphone);
- }] resume];
- dispatch_semaphore_wait(wait_semaphone, DISPATCH_TIME_FOREVER);
- dispatch_release(wait_semaphone);
- if (out_error)
- *out_error = [error autorelease];
- if (out_response)
- *out_response = [response autorelease];
- return [result autorelease];
-#else
- return [NSURLConnection sendSynchronousRequest:req
- returningResponse:out_response
- error:out_error];
-#endif
-}
-@interface HTTPMultipartUpload(PrivateMethods)
-- (NSString *)multipartBoundary;
-// Each of the following methods will append the starting multipart boundary,
-// but not the ending one.
-- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value;
-- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name;
-- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name;
-@end
-
-@implementation HTTPMultipartUpload
-//=============================================================================
-#pragma mark -
-#pragma mark || Private ||
-//=============================================================================
-- (NSString *)multipartBoundary {
- // The boundary has 27 '-' characters followed by 16 hex digits
- return [NSString stringWithFormat:@"---------------------------%08X%08X",
- rand(), rand()];
-}
-
-//=============================================================================
-- (NSData *)formDataForKey:(NSString *)key value:(NSString *)value {
- NSString *escaped = PercentEncodeNSString(key);
- NSString *fmt =
- @"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n";
- NSString *form = [NSString stringWithFormat:fmt, boundary_, escaped, value];
-
- return [form dataUsingEncoding:NSUTF8StringEncoding];
-}
-
-//=============================================================================
-- (NSData *)formDataForFileContents:(NSData *)contents name:(NSString *)name {
- NSMutableData *data = [NSMutableData data];
- NSString *escaped = PercentEncodeNSString(name);
- NSString *fmt = @"--%@\r\nContent-Disposition: form-data; name=\"%@\"; "
- "filename=\"minidump.dmp\"\r\nContent-Type: application/octet-stream\r\n\r\n";
- NSString *pre = [NSString stringWithFormat:fmt, boundary_, escaped];
-
- [data appendData:[pre dataUsingEncoding:NSUTF8StringEncoding]];
- [data appendData:contents];
-
- return data;
-}
-
-//=============================================================================
-- (NSData *)formDataForFile:(NSString *)file name:(NSString *)name {
- NSData *contents = [NSData dataWithContentsOfFile:file];
-
- return [self formDataForFileContents:contents name:name];
-}
-
-//=============================================================================
-#pragma mark -
-#pragma mark || Public ||
-//=============================================================================
-- (id)initWithURL:(NSURL *)url {
- if ((self = [super init])) {
- url_ = [url copy];
- boundary_ = [[self multipartBoundary] retain];
- files_ = [[NSMutableDictionary alloc] init];
- }
-
- return self;
-}
-
-//=============================================================================
-- (void)dealloc {
- [url_ release];
- [parameters_ release];
- [files_ release];
- [boundary_ release];
- [response_ release];
-
- [super dealloc];
-}
-
-//=============================================================================
-- (NSURL *)URL {
- return url_;
-}
-
-//=============================================================================
-- (void)setParameters:(NSDictionary *)parameters {
- if (parameters != parameters_) {
- [parameters_ release];
- parameters_ = [parameters copy];
- }
-}
-
-//=============================================================================
-- (NSDictionary *)parameters {
- return parameters_;
-}
-
-//=============================================================================
-- (void)addFileAtPath:(NSString *)path name:(NSString *)name {
- [files_ setObject:path forKey:name];
-}
-
-//=============================================================================
-- (void)addFileContents:(NSData *)data name:(NSString *)name {
- [files_ setObject:data forKey:name];
-}
-
-//=============================================================================
-- (NSDictionary *)files {
- return files_;
-}
-
-//=============================================================================
-- (NSData *)send:(NSError **)error {
- NSMutableURLRequest *req =
- [[NSMutableURLRequest alloc]
- initWithURL:url_ cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:10.0 ];
-
- NSMutableData *postBody = [NSMutableData data];
-
- [req setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",
- boundary_] forHTTPHeaderField:@"Content-type"];
-
- // Add any parameters to the message
- NSArray *parameterKeys = [parameters_ allKeys];
- NSString *key;
-
- NSInteger count = [parameterKeys count];
- for (NSInteger i = 0; i < count; ++i) {
- key = [parameterKeys objectAtIndex:i];
- [postBody appendData:[self formDataForKey:key
- value:[parameters_ objectForKey:key]]];
- }
-
- // Add any files to the message
- NSArray *fileNames = [files_ allKeys];
- count = [fileNames count];
- for (NSInteger i = 0; i < count; ++i) {
- NSString *name = [fileNames objectAtIndex:i];
- id fileOrData = [files_ objectForKey:name];
- NSData *fileData;
-
- // The object can be either the path to a file (NSString) or the contents
- // of the file (NSData).
- if ([fileOrData isKindOfClass:[NSData class]])
- fileData = [self formDataForFileContents:fileOrData name:name];
- else
- fileData = [self formDataForFile:fileOrData name:name];
-
- [postBody appendData:fileData];
- }
-
- NSString *epilogue = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary_];
- [postBody appendData:[epilogue dataUsingEncoding:NSUTF8StringEncoding]];
-
- [req setHTTPBody:postBody];
- [req setHTTPMethod:@"POST"];
-
- [response_ release];
- response_ = nil;
-
- NSData *data = nil;
- if ([[req URL] isFileURL]) {
- [[req HTTPBody] writeToURL:[req URL] options:0 error:error];
- } else {
- NSURLResponse *response = nil;
- data = SendSynchronousNSURLRequest(req, &response, error);
- response_ = (NSHTTPURLResponse *)[response retain];
- }
- [req release];
-
- return data;
-}
-
-//=============================================================================
-- (NSHTTPURLResponse *)response {
- return response_;
-}
-
-@end
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h
deleted file mode 100644
index 8df9165bb..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.h
+++ /dev/null
@@ -1,301 +0,0 @@
-// 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.
-//
-// MachIPC.h
-//
-// Some helpful wrappers for using Mach IPC calls
-
-#ifndef MACH_IPC_H__
-#define MACH_IPC_H__
-
-#import <mach/mach.h>
-#import <mach/message.h>
-#import <servers/bootstrap.h>
-#import <sys/types.h>
-
-#import <CoreServices/CoreServices.h>
-
-//==============================================================================
-// DISCUSSION:
-//
-// The three main classes of interest are
-//
-// MachMessage: a wrapper for a mach message of the following form
-// mach_msg_header_t
-// mach_msg_body_t
-// optional descriptors
-// optional extra message data
-//
-// MachReceiveMessage and MachSendMessage subclass MachMessage
-// and are used instead of MachMessage which is an abstract base class
-//
-// ReceivePort:
-// Represents a mach port for which we have receive rights
-//
-// MachPortSender:
-// Represents a mach port for which we have send rights
-//
-// Here's an example to receive a message on a server port:
-//
-// // This creates our named server port
-// ReceivePort receivePort("com.Google.MyService");
-//
-// MachReceiveMessage message;
-// kern_return_t result = receivePort.WaitForMessage(&message, 0);
-//
-// if (result == KERN_SUCCESS && message.GetMessageID() == 57) {
-// mach_port_t task = message.GetTranslatedPort(0);
-// mach_port_t thread = message.GetTranslatedPort(1);
-//
-// char *messageString = message.GetData();
-//
-// printf("message string = %s\n", messageString);
-// }
-//
-// Here is an example of using these classes to send a message to this port:
-//
-// // send to already named port
-// MachPortSender sender("com.Google.MyService");
-// MachSendMessage message(57); // our message ID is 57
-//
-// // add some ports to be translated for us
-// message.AddDescriptor(mach_task_self()); // our task
-// message.AddDescriptor(mach_thread_self()); // this thread
-//
-// char messageString[] = "Hello server!\n";
-// message.SetData(messageString, strlen(messageString)+1);
-//
-// kern_return_t result = sender.SendMessage(message, 1000); // timeout 1000ms
-//
-
-namespace google_breakpad {
-#define PRINT_MACH_RESULT(result_, message_) \
- printf(message_" %s (%d)\n", mach_error_string(result_), result_ );
-
-//==============================================================================
-// A wrapper class for mach_msg_port_descriptor_t (with same memory layout)
-// with convenient constructors and accessors
-class MachMsgPortDescriptor : public mach_msg_port_descriptor_t {
- public:
- // General-purpose constructor
- MachMsgPortDescriptor(mach_port_t in_name,
- mach_msg_type_name_t in_disposition) {
- name = in_name;
- pad1 = 0;
- pad2 = 0;
- disposition = in_disposition;
- type = MACH_MSG_PORT_DESCRIPTOR;
- }
-
- // For passing send rights to a port
- MachMsgPortDescriptor(mach_port_t in_name) {
- name = in_name;
- pad1 = 0;
- pad2 = 0;
- disposition = MACH_MSG_TYPE_COPY_SEND;
- type = MACH_MSG_PORT_DESCRIPTOR;
- }
-
- // Copy constructor
- MachMsgPortDescriptor(const MachMsgPortDescriptor& desc) {
- name = desc.name;
- pad1 = desc.pad1;
- pad2 = desc.pad2;
- disposition = desc.disposition;
- type = desc.type;
- }
-
- mach_port_t GetMachPort() const {
- return name;
- }
-
- mach_msg_type_name_t GetDisposition() const {
- return disposition;
- }
-
- // For convenience
- operator mach_port_t() const {
- return GetMachPort();
- }
-};
-
-//==============================================================================
-// MachMessage: a wrapper for a mach message
-// (mach_msg_header_t, mach_msg_body_t, extra data)
-//
-// This considerably simplifies the construction of a message for sending
-// and the getting at relevant data and descriptors for the receiver.
-//
-// Currently the combined size of the descriptors plus data must be
-// less than 1024. But as a benefit no memory allocation is necessary.
-//
-// TODO: could consider adding malloc() support for very large messages
-//
-// A MachMessage object is used by ReceivePort::WaitForMessage
-// and MachPortSender::SendMessage
-//
-class MachMessage {
- public:
-
- // The receiver of the message can retrieve the raw data this way
- uint8_t *GetData() {
- return GetDataLength() > 0 ? GetDataPacket()->data : NULL;
- }
-
- uint32_t GetDataLength() {
- return EndianU32_LtoN(GetDataPacket()->data_length);
- }
-
- // The message ID may be used as a code identifying the type of message
- void SetMessageID(int32_t message_id) {
- GetDataPacket()->id = EndianU32_NtoL(message_id);
- }
-
- int32_t GetMessageID() { return EndianU32_LtoN(GetDataPacket()->id); }
-
- // Adds a descriptor (typically a mach port) to be translated
- // returns true if successful, otherwise not enough space
- bool AddDescriptor(const MachMsgPortDescriptor &desc);
-
- int GetDescriptorCount() const { return body.msgh_descriptor_count; }
- MachMsgPortDescriptor *GetDescriptor(int n);
-
- // Convenience method which gets the mach port described by the descriptor
- mach_port_t GetTranslatedPort(int n);
-
- // A simple message is one with no descriptors
- bool IsSimpleMessage() const { return GetDescriptorCount() == 0; }
-
- // Sets raw data for the message (returns false if not enough space)
- bool SetData(void *data, int32_t data_length);
-
- protected:
- // Consider this an abstract base class - must create an actual instance
- // of MachReceiveMessage or MachSendMessage
-
- MachMessage() {
- memset(this, 0, sizeof(MachMessage));
- }
-
- friend class ReceivePort;
- friend class MachPortSender;
-
- // Represents raw data in our message
- struct MessageDataPacket {
- int32_t id; // little-endian
- int32_t data_length; // little-endian
- uint8_t data[1]; // actual size limited by sizeof(MachMessage)
- };
-
- MessageDataPacket* GetDataPacket();
-
- void SetDescriptorCount(int n);
- void SetDescriptor(int n, const MachMsgPortDescriptor &desc);
-
- // Returns total message size setting msgh_size in the header to this value
- mach_msg_size_t CalculateSize();
-
- mach_msg_header_t head;
- mach_msg_body_t body;
- uint8_t padding[1024]; // descriptors and data may be embedded here
-};
-
-//==============================================================================
-// MachReceiveMessage and MachSendMessage are useful to separate the idea
-// of a mach message being sent and being received, and adds increased type
-// safety:
-// ReceivePort::WaitForMessage() only accepts a MachReceiveMessage
-// MachPortSender::SendMessage() only accepts a MachSendMessage
-
-//==============================================================================
-class MachReceiveMessage : public MachMessage {
- public:
- MachReceiveMessage() : MachMessage() {};
-};
-
-//==============================================================================
-class MachSendMessage : public MachMessage {
- public:
- MachSendMessage(int32_t message_id);
-};
-
-//==============================================================================
-// Represents a mach port for which we have receive rights
-class ReceivePort {
- public:
- // Creates a new mach port for receiving messages and registers a name for it
- explicit ReceivePort(const char *receive_port_name);
-
- // Given an already existing mach port, use it. We take ownership of the
- // port and deallocate it in our destructor.
- explicit ReceivePort(mach_port_t receive_port);
-
- // Create a new mach port for receiving messages
- ReceivePort();
-
- ~ReceivePort();
-
- // Waits on the mach port until message received or timeout
- kern_return_t WaitForMessage(MachReceiveMessage *out_message,
- mach_msg_timeout_t timeout);
-
- // The underlying mach port that we wrap
- mach_port_t GetPort() const { return port_; }
-
- private:
- ReceivePort(const ReceivePort&); // disable copy c-tor
-
- mach_port_t port_;
- kern_return_t init_result_;
-};
-
-//==============================================================================
-// Represents a mach port for which we have send rights
-class MachPortSender {
- public:
- // get a port with send rights corresponding to a named registered service
- explicit MachPortSender(const char *receive_port_name);
-
-
- // Given an already existing mach port, use it.
- explicit MachPortSender(mach_port_t send_port);
-
- kern_return_t SendMessage(MachSendMessage &message,
- mach_msg_timeout_t timeout);
-
- private:
- MachPortSender(const MachPortSender&); // disable copy c-tor
-
- mach_port_t send_port_;
- kern_return_t init_result_;
-};
-
-} // namespace google_breakpad
-
-#endif // MACH_IPC_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm b/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm
deleted file mode 100644
index dc9773f77..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/MachIPC.mm
+++ /dev/null
@@ -1,306 +0,0 @@
-// 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.
-//
-// MachIPC.mm
-// Wrapper for mach IPC calls
-
-#import <stdio.h>
-#import "MachIPC.h"
-#include "common/mac/bootstrap_compat.h"
-
-namespace google_breakpad {
-//==============================================================================
-MachSendMessage::MachSendMessage(int32_t message_id) : MachMessage() {
- head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
-
- // head.msgh_remote_port = ...; // filled out in MachPortSender::SendMessage()
- head.msgh_local_port = MACH_PORT_NULL;
- head.msgh_reserved = 0;
- head.msgh_id = 0;
-
- SetDescriptorCount(0); // start out with no descriptors
-
- SetMessageID(message_id);
- SetData(NULL, 0); // client may add data later
-}
-
-//==============================================================================
-// returns true if successful
-bool MachMessage::SetData(void *data,
- int32_t data_length) {
- // first check to make sure we have enough space
- size_t size = CalculateSize();
- size_t new_size = size + data_length;
-
- if (new_size > sizeof(MachMessage)) {
- return false; // not enough space
- }
-
- GetDataPacket()->data_length = EndianU32_NtoL(data_length);
- if (data) memcpy(GetDataPacket()->data, data, data_length);
-
- CalculateSize();
-
- return true;
-}
-
-//==============================================================================
-// calculates and returns the total size of the message
-// Currently, the entire message MUST fit inside of the MachMessage
-// messsage size <= sizeof(MachMessage)
-mach_msg_size_t MachMessage::CalculateSize() {
- size_t size = sizeof(mach_msg_header_t) + sizeof(mach_msg_body_t);
-
- // add space for MessageDataPacket
- int32_t alignedDataLength = (GetDataLength() + 3) & ~0x3;
- size += 2*sizeof(int32_t) + alignedDataLength;
-
- // add space for descriptors
- size += GetDescriptorCount() * sizeof(MachMsgPortDescriptor);
-
- head.msgh_size = static_cast<mach_msg_size_t>(size);
-
- return head.msgh_size;
-}
-
-//==============================================================================
-MachMessage::MessageDataPacket *MachMessage::GetDataPacket() {
- size_t desc_size = sizeof(MachMsgPortDescriptor)*GetDescriptorCount();
- MessageDataPacket *packet =
- reinterpret_cast<MessageDataPacket*>(padding + desc_size);
-
- return packet;
-}
-
-//==============================================================================
-void MachMessage::SetDescriptor(int n,
- const MachMsgPortDescriptor &desc) {
- MachMsgPortDescriptor *desc_array =
- reinterpret_cast<MachMsgPortDescriptor*>(padding);
- desc_array[n] = desc;
-}
-
-//==============================================================================
-// returns true if successful otherwise there was not enough space
-bool MachMessage::AddDescriptor(const MachMsgPortDescriptor &desc) {
- // first check to make sure we have enough space
- int size = CalculateSize();
- size_t new_size = size + sizeof(MachMsgPortDescriptor);
-
- if (new_size > sizeof(MachMessage)) {
- return false; // not enough space
- }
-
- // unfortunately, we need to move the data to allow space for the
- // new descriptor
- u_int8_t *p = reinterpret_cast<u_int8_t*>(GetDataPacket());
- bcopy(p, p+sizeof(MachMsgPortDescriptor), GetDataLength()+2*sizeof(int32_t));
-
- SetDescriptor(GetDescriptorCount(), desc);
- SetDescriptorCount(GetDescriptorCount() + 1);
-
- CalculateSize();
-
- return true;
-}
-
-//==============================================================================
-void MachMessage::SetDescriptorCount(int n) {
- body.msgh_descriptor_count = n;
-
- if (n > 0) {
- head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
- } else {
- head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
- }
-}
-
-//==============================================================================
-MachMsgPortDescriptor *MachMessage::GetDescriptor(int n) {
- if (n < GetDescriptorCount()) {
- MachMsgPortDescriptor *desc =
- reinterpret_cast<MachMsgPortDescriptor*>(padding);
- return desc + n;
- }
-
- return nil;
-}
-
-//==============================================================================
-mach_port_t MachMessage::GetTranslatedPort(int n) {
- if (n < GetDescriptorCount()) {
- return GetDescriptor(n)->GetMachPort();
- }
- return MACH_PORT_NULL;
-}
-
-#pragma mark -
-
-//==============================================================================
-// create a new mach port for receiving messages and register a name for it
-ReceivePort::ReceivePort(const char *receive_port_name) {
- mach_port_t current_task = mach_task_self();
-
- init_result_ = mach_port_allocate(current_task,
- MACH_PORT_RIGHT_RECEIVE,
- &port_);
-
- if (init_result_ != KERN_SUCCESS)
- return;
-
- init_result_ = mach_port_insert_right(current_task,
- port_,
- port_,
- MACH_MSG_TYPE_MAKE_SEND);
-
- if (init_result_ != KERN_SUCCESS)
- return;
-
- mach_port_t task_bootstrap_port = 0;
- init_result_ = task_get_bootstrap_port(current_task, &task_bootstrap_port);
-
- if (init_result_ != KERN_SUCCESS)
- return;
-
- init_result_ = breakpad::BootstrapRegister(
- bootstrap_port,
- const_cast<char*>(receive_port_name),
- port_);
-}
-
-//==============================================================================
-// create a new mach port for receiving messages
-ReceivePort::ReceivePort() {
- mach_port_t current_task = mach_task_self();
-
- init_result_ = mach_port_allocate(current_task,
- MACH_PORT_RIGHT_RECEIVE,
- &port_);
-
- if (init_result_ != KERN_SUCCESS)
- return;
-
- init_result_ = mach_port_insert_right(current_task,
- port_,
- port_,
- MACH_MSG_TYPE_MAKE_SEND);
-}
-
-//==============================================================================
-// Given an already existing mach port, use it. We take ownership of the
-// port and deallocate it in our destructor.
-ReceivePort::ReceivePort(mach_port_t receive_port)
- : port_(receive_port),
- init_result_(KERN_SUCCESS) {
-}
-
-//==============================================================================
-ReceivePort::~ReceivePort() {
- if (init_result_ == KERN_SUCCESS)
- mach_port_deallocate(mach_task_self(), port_);
-}
-
-//==============================================================================
-kern_return_t ReceivePort::WaitForMessage(MachReceiveMessage *out_message,
- mach_msg_timeout_t timeout) {
- if (!out_message) {
- return KERN_INVALID_ARGUMENT;
- }
-
- // return any error condition encountered in constructor
- if (init_result_ != KERN_SUCCESS)
- return init_result_;
-
- out_message->head.msgh_bits = 0;
- out_message->head.msgh_local_port = port_;
- out_message->head.msgh_remote_port = MACH_PORT_NULL;
- out_message->head.msgh_reserved = 0;
- out_message->head.msgh_id = 0;
-
- mach_msg_option_t options = MACH_RCV_MSG;
- if (timeout != MACH_MSG_TIMEOUT_NONE)
- options |= MACH_RCV_TIMEOUT;
- kern_return_t result = mach_msg(&out_message->head,
- options,
- 0,
- sizeof(MachMessage),
- port_,
- timeout, // timeout in ms
- MACH_PORT_NULL);
-
- return result;
-}
-
-#pragma mark -
-
-//==============================================================================
-// get a port with send rights corresponding to a named registered service
-MachPortSender::MachPortSender(const char *receive_port_name) {
- mach_port_t task_bootstrap_port = 0;
- init_result_ = task_get_bootstrap_port(mach_task_self(),
- &task_bootstrap_port);
-
- if (init_result_ != KERN_SUCCESS)
- return;
-
- init_result_ = bootstrap_look_up(task_bootstrap_port,
- const_cast<char*>(receive_port_name),
- &send_port_);
-}
-
-//==============================================================================
-MachPortSender::MachPortSender(mach_port_t send_port)
- : send_port_(send_port),
- init_result_(KERN_SUCCESS) {
-}
-
-//==============================================================================
-kern_return_t MachPortSender::SendMessage(MachSendMessage &message,
- mach_msg_timeout_t timeout) {
- if (message.head.msgh_size == 0) {
- return KERN_INVALID_VALUE; // just for safety -- never should occur
- };
-
- if (init_result_ != KERN_SUCCESS)
- return init_result_;
-
- message.head.msgh_remote_port = send_port_;
-
- kern_return_t result = mach_msg(&message.head,
- MACH_SEND_MSG | MACH_SEND_TIMEOUT,
- message.head.msgh_size,
- 0,
- MACH_PORT_NULL,
- timeout, // timeout in ms
- MACH_PORT_NULL);
-
- return result;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc
deleted file mode 100644
index 4e5f5534a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.cc
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/mac/arch_utilities.h"
-
-#include <mach-o/arch.h>
-#include <mach-o/fat.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef CPU_SUBTYPE_ARM_V7S
-#define CPU_SUBTYPE_ARM_V7S (static_cast<cpu_subtype_t>(11))
-#endif // CPU_SUBTYPE_ARM_V7S
-
-#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#endif // CPU_TYPE_ARM64
-
-#ifndef CPU_SUBTYPE_ARM64_ALL
-#define CPU_SUBTYPE_ARM64_ALL (static_cast<cpu_subtype_t>(0))
-#endif // CPU_SUBTYPE_ARM64_ALL
-
-namespace {
-
-const NXArchInfo* ArchInfo_arm64() {
- NXArchInfo* arm64 = new NXArchInfo;
- *arm64 = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_V7);
- arm64->name = "arm64";
- arm64->cputype = CPU_TYPE_ARM64;
- arm64->cpusubtype = CPU_SUBTYPE_ARM64_ALL;
- arm64->description = "arm 64";
- return arm64;
-}
-
-const NXArchInfo* ArchInfo_armv7s() {
- NXArchInfo* armv7s = new NXArchInfo;
- *armv7s = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_V7);
- armv7s->name = "armv7s";
- armv7s->cpusubtype = CPU_SUBTYPE_ARM_V7S;
- armv7s->description = "arm v7s";
- return armv7s;
-}
-
-} // namespace
-
-namespace google_breakpad {
-
-const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name) {
- // TODO: Remove this when the OS knows about arm64.
- if (!strcmp("arm64", arch_name))
- return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_ALL);
-
- // TODO: Remove this when the OS knows about armv7s.
- if (!strcmp("armv7s", arch_name))
- return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S);
-
- return NXGetArchInfoFromName(arch_name);
-}
-
-const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype) {
- // TODO: Remove this when the OS knows about arm64.
- if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_ALL) {
- static const NXArchInfo* arm64 = ArchInfo_arm64();
- return arm64;
- }
-
- // TODO: Remove this when the OS knows about armv7s.
- if (cpu_type == CPU_TYPE_ARM && cpu_subtype == CPU_SUBTYPE_ARM_V7S) {
- static const NXArchInfo* armv7s = ArchInfo_armv7s();
- return armv7s;
- }
-
- return NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
-}
-
-} // namespace google_breakpad
-
-#ifndef __APPLE__
-namespace {
-
-enum Architecture {
- kArch_i386 = 0,
- kArch_x86_64,
- kArch_arm,
- kArch_arm64,
- kArch_ppc,
- // This must be last.
- kNumArchitectures
-};
-
-// enum Architecture above and kKnownArchitectures below
-// must be kept in sync.
-const NXArchInfo kKnownArchitectures[] = {
- {
- "i386",
- CPU_TYPE_I386,
- CPU_SUBTYPE_I386_ALL,
- NX_LittleEndian,
- "Intel 80x86"
- },
- {
- "x86_64",
- CPU_TYPE_X86_64,
- CPU_SUBTYPE_X86_64_ALL,
- NX_LittleEndian,
- "Intel x86-64"
- },
- {
- "arm",
- CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_ALL,
- NX_LittleEndian,
- "ARM"
- },
- {
- "arm64",
- CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_ALL,
- NX_LittleEndian,
- "ARM64"
- },
- {
- "ppc",
- CPU_TYPE_POWERPC,
- CPU_SUBTYPE_POWERPC_ALL,
- NX_BigEndian,
- "PowerPC"
- }
-};
-
-} // namespace
-
-const NXArchInfo *NXGetLocalArchInfo(void) {
- Architecture arch;
-#if defined(__i386__)
- arch = kArch_i386;
-#elif defined(__x86_64__)
- arch = kArch_x86_64;
-#elif defined(__arm64)
- arch = kArch_arm64;
-#elif defined(__arm__)
- arch = kArch_arm;
-#elif defined(__powerpc__)
- arch = kArch_ppc;
-#else
- #error "Unsupported CPU architecture"
-#endif
- return &kKnownArchitectures[arch];
-}
-
-const NXArchInfo *NXGetArchInfoFromName(const char *name) {
- for (int arch = 0; arch < kNumArchitectures; ++arch) {
- if (!strcmp(name, kKnownArchitectures[arch].name)) {
- return &kKnownArchitectures[arch];
- }
- }
- return NULL;
-}
-
-const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
- cpu_subtype_t cpusubtype) {
- for (int arch = 0; arch < kNumArchitectures; ++arch) {
- if (kKnownArchitectures[arch].cputype == cputype) {
- return &kKnownArchitectures[arch];
- }
- }
- return NULL;
-}
-
-struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
- cpu_subtype_t cpusubtype,
- struct fat_arch *fat_archs,
- uint32_t nfat_archs) {
- for (uint32_t f = 0; f < nfat_archs; ++f) {
- if (fat_archs[f].cputype == cputype) {
- return &fat_archs[f];
- }
- }
- return NULL;
-}
-#endif // !__APPLE__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h
deleted file mode 100644
index 397c1f587..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/arch_utilities.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// arch_utilities.h: Utilities for architecture introspection for Mac platform.
-
-#ifndef COMMON_MAC_ARCH_UTILITIES_H__
-#define COMMON_MAC_ARCH_UTILITIES_H__
-
-#include <mach-o/arch.h>
-
-namespace google_breakpad {
-
-// Custom implementation of |NXGetArchInfoFromName| and
-// |NXGetArchInfoFromCpuType| that handle newer CPU on older OSes.
-const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name);
-const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype);
-
-} // namespace google_breakpad
-
-#endif // COMMON_MAC_ARCH_UTILITIES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc
deleted file mode 100644
index d875d95b5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/mac/bootstrap_compat.h"
-
-namespace breakpad {
-
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-kern_return_t BootstrapRegister(mach_port_t bp,
- name_t service_name,
- mach_port_t sp) {
- return bootstrap_register(bp, service_name, sp);
-}
-#pragma GCC diagnostic warning "-Wdeprecated-declarations"
-
-} // namesapce breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h b/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h
deleted file mode 100644
index 8ca7357c3..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/bootstrap_compat.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012, 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 COMMON_MAC_BOOTSTRAP_COMPAT_H_
-#define COMMON_MAC_BOOTSTRAP_COMPAT_H_
-
-#include <servers/bootstrap.h>
-
-namespace breakpad {
-
-// Wrapper for bootstrap_register to avoid deprecation warnings.
-//
-// In 10.6, it's possible to call bootstrap_check_in as the one-stop-shop for
-// handling what bootstrap_register is used for. In 10.5, bootstrap_check_in
-// can't check in a service whose name has not yet been registered, despite
-// bootstrap_register being marked as deprecated in that OS release. Breakpad
-// needs to register new service names, and in 10.5, calling
-// bootstrap_register is the only way to achieve that. Attempts to call
-// bootstrap_check_in for a new service name on 10.5 will result in
-// BOOTSTRAP_UNKNOWN_SERVICE being returned rather than registration of the
-// new service name.
-kern_return_t BootstrapRegister(mach_port_t bp,
- name_t service_name,
- mach_port_t sp);
-
-} // namespace breakpad
-
-#endif // COMMON_MAC_BOOTSTRAP_COMPAT_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h b/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h
deleted file mode 100644
index b7bbc0b95..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/byteswap.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jim@mozilla.com> <jimb@red-bean.com>
-
-// byteswap.h: Overloaded functions for conveniently byteswapping values.
-
-#ifndef COMMON_MAC_BYTESWAP_H_
-#define COMMON_MAC_BYTESWAP_H_
-
-#ifdef __APPLE__
-#include <libkern/OSByteOrder.h>
-
-static inline uint16_t ByteSwap(uint16_t v) { return OSSwapInt16(v); }
-static inline uint32_t ByteSwap(uint32_t v) { return OSSwapInt32(v); }
-static inline uint64_t ByteSwap(uint64_t v) { return OSSwapInt64(v); }
-static inline int16_t ByteSwap(int16_t v) { return OSSwapInt16(v); }
-static inline int32_t ByteSwap(int32_t v) { return OSSwapInt32(v); }
-static inline int64_t ByteSwap(int64_t v) { return OSSwapInt64(v); }
-
-#elif defined(__linux__)
-// For NXByteOrder
-#include <architecture/byte_order.h>
-#include <stdint.h>
-#include <endian.h>
-#include_next <byteswap.h>
-
-static inline uint16_t ByteSwap(uint16_t v) { return bswap_16(v); }
-static inline uint32_t ByteSwap(uint32_t v) { return bswap_32(v); }
-static inline uint64_t ByteSwap(uint64_t v) { return bswap_64(v); }
-static inline int16_t ByteSwap(int16_t v) { return bswap_16(v); }
-static inline int32_t ByteSwap(int32_t v) { return bswap_32(v); }
-static inline int64_t ByteSwap(int64_t v) { return bswap_64(v); }
-
-static inline NXByteOrder NXHostByteOrder() {
-#ifdef __LITTLE_ENDIAN
- return NX_LittleEndian;
-#else
- return NX_BigEndian;
-#endif
-}
-
-#endif // __APPLE__
-
-#endif // COMMON_MAC_BYTESWAP_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc
deleted file mode 100644
index b20a05586..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.cc
+++ /dev/null
@@ -1,646 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_syms.mm: Create a symbol file for use with minidumps
-
-#include "common/mac/dump_syms.h"
-
-#include <assert.h>
-#include <dirent.h>
-#include <errno.h>
-#include <libgen.h>
-#include <mach-o/arch.h>
-#include <mach-o/fat.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/dwarf_cfi_to_module.h"
-#include "common/dwarf_cu_to_module.h"
-#include "common/dwarf_line_to_module.h"
-#include "common/mac/file_id.h"
-#include "common/mac/arch_utilities.h"
-#include "common/mac/macho_reader.h"
-#include "common/module.h"
-#include "common/scoped_ptr.h"
-#include "common/stabs_reader.h"
-#include "common/stabs_to_module.h"
-#include "common/symbol_data.h"
-
-#ifndef CPU_TYPE_ARM
-#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12))
-#endif // CPU_TYPE_ARM
-
-#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 (static_cast<cpu_type_t>(16777228))
-#endif // CPU_TYPE_ARM64
-
-using dwarf2reader::ByteReader;
-using google_breakpad::DwarfCUToModule;
-using google_breakpad::DwarfLineToModule;
-using google_breakpad::FileID;
-using google_breakpad::mach_o::FatReader;
-using google_breakpad::mach_o::Section;
-using google_breakpad::mach_o::Segment;
-using google_breakpad::Module;
-using google_breakpad::StabsReader;
-using google_breakpad::StabsToModule;
-using google_breakpad::scoped_ptr;
-using std::make_pair;
-using std::pair;
-using std::string;
-using std::vector;
-
-namespace {
-// Return a vector<string> with absolute paths to all the entries
-// in directory (excluding . and ..).
-vector<string> list_directory(const string& directory) {
- vector<string> entries;
- DIR* dir = opendir(directory.c_str());
- if (!dir) {
- return entries;
- }
-
- string path = directory;
- if (path[path.length() - 1] != '/') {
- path += '/';
- }
-
- struct dirent* entry = NULL;
- while ((entry = readdir(dir))) {
- if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
- entries.push_back(path + entry->d_name);
- }
- }
-
- closedir(dir);
- return entries;
-}
-}
-
-namespace google_breakpad {
-
-bool DumpSymbols::Read(const string &filename) {
- struct stat st;
- if (stat(filename.c_str(), &st) == -1) {
- fprintf(stderr, "Could not access object file %s: %s\n",
- filename.c_str(), strerror(errno));
- return false;
- }
-
- input_pathname_ = filename;
-
- // Does this filename refer to a dSYM bundle?
- string contents_path = input_pathname_ + "/Contents/Resources/DWARF";
- if (S_ISDIR(st.st_mode) &&
- access(contents_path.c_str(), F_OK) == 0) {
- // If there's one file under Contents/Resources/DWARF then use that,
- // otherwise bail out.
- const vector<string> entries = list_directory(contents_path);
- if (entries.size() == 0) {
- fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n",
- input_pathname_.c_str());
- return false;
- }
- if (entries.size() > 1) {
- fprintf(stderr, "Too many DWARF files in bundle: %s\n",
- input_pathname_.c_str());
- return false;
- }
-
- object_filename_ = entries[0];
- } else {
- object_filename_ = input_pathname_;
- }
-
- // Read the file's contents into memory.
- bool read_ok = true;
- string error;
- if (stat(object_filename_.c_str(), &st) != -1) {
- FILE* f = fopen(object_filename_.c_str(), "rb");
- if (f) {
- contents_.reset(new uint8_t[st.st_size]);
- off_t total = 0;
- while (total < st.st_size && !feof(f)) {
- size_t read = fread(&contents_[0] + total, 1, st.st_size - total, f);
- if (read == 0) {
- if (ferror(f)) {
- read_ok = false;
- error = strerror(errno);
- }
- break;
- }
- total += read;
- }
- fclose(f);
- } else {
- error = strerror(errno);
- }
- }
-
- if (!read_ok) {
- fprintf(stderr, "Error reading object file: %s: %s\n",
- object_filename_.c_str(),
- error.c_str());
- return false;
- }
-
- // Get the list of object files present in the file.
- FatReader::Reporter fat_reporter(object_filename_);
- FatReader fat_reader(&fat_reporter);
- if (!fat_reader.Read(&contents_[0],
- st.st_size)) {
- return false;
- }
-
- // Get our own copy of fat_reader's object file list.
- size_t object_files_count;
- const SuperFatArch *object_files =
- fat_reader.object_files(&object_files_count);
- if (object_files_count == 0) {
- fprintf(stderr, "Fat binary file contains *no* architectures: %s\n",
- object_filename_.c_str());
- return false;
- }
- object_files_.resize(object_files_count);
- memcpy(&object_files_[0], object_files,
- sizeof(SuperFatArch) * object_files_count);
-
- return true;
-}
-
-bool DumpSymbols::SetArchitecture(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype) {
- // Find the best match for the architecture the user requested.
- const SuperFatArch *best_match = FindBestMatchForArchitecture(
- cpu_type, cpu_subtype);
- if (!best_match) return false;
-
- // Record the selected object file.
- selected_object_file_ = best_match;
- return true;
-}
-
-bool DumpSymbols::SetArchitecture(const std::string &arch_name) {
- bool arch_set = false;
- const NXArchInfo *arch_info =
- google_breakpad::BreakpadGetArchInfoFromName(arch_name.c_str());
- if (arch_info) {
- arch_set = SetArchitecture(arch_info->cputype, arch_info->cpusubtype);
- }
- return arch_set;
-}
-
-SuperFatArch* DumpSymbols::FindBestMatchForArchitecture(
- cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
- // Check if all the object files can be converted to struct fat_arch.
- bool can_convert_to_fat_arch = true;
- vector<struct fat_arch> fat_arch_vector;
- for (vector<SuperFatArch>::const_iterator it = object_files_.begin();
- it != object_files_.end();
- ++it) {
- struct fat_arch arch;
- bool success = it->ConvertToFatArch(&arch);
- if (!success) {
- can_convert_to_fat_arch = false;
- break;
- }
- fat_arch_vector.push_back(arch);
- }
-
- // If all the object files can be converted to struct fat_arch, use
- // NXFindBestFatArch.
- if (can_convert_to_fat_arch) {
- const struct fat_arch *best_match
- = NXFindBestFatArch(cpu_type, cpu_subtype, &fat_arch_vector[0],
- static_cast<uint32_t>(fat_arch_vector.size()));
-
- for (size_t i = 0; i < fat_arch_vector.size(); ++i) {
- if (best_match == &fat_arch_vector[i])
- return &object_files_[i];
- }
- assert(best_match == NULL);
- return NULL;
- }
-
- // Check for an exact match with cpu_type and cpu_subtype.
- for (vector<SuperFatArch>::iterator it = object_files_.begin();
- it != object_files_.end();
- ++it) {
- if (static_cast<cpu_type_t>(it->cputype) == cpu_type &&
- static_cast<cpu_subtype_t>(it->cpusubtype) == cpu_subtype)
- return &*it;
- }
-
- // No exact match found.
- // TODO(erikchen): If it becomes necessary, we can copy the implementation of
- // NXFindBestFatArch, located at
- // http://web.mit.edu/darwin/src/modules/cctools/libmacho/arch.c.
- fprintf(stderr, "Failed to find an exact match for an object file with cpu "
- "type: %d and cpu subtype: %d. Furthermore, at least one object file is "
- "larger than 2**32.\n", cpu_type, cpu_subtype);
- return NULL;
-}
-
-string DumpSymbols::Identifier() {
- FileID file_id(object_filename_.c_str());
- unsigned char identifier_bytes[16];
- cpu_type_t cpu_type = selected_object_file_->cputype;
- cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype;
- if (!file_id.MachoIdentifier(cpu_type, cpu_subtype, identifier_bytes)) {
- fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n",
- object_filename_.c_str());
- return "";
- }
-
- char identifier_string[40];
- FileID::ConvertIdentifierToString(identifier_bytes, identifier_string,
- sizeof(identifier_string));
-
- string compacted(identifier_string);
- for(size_t i = compacted.find('-'); i != string::npos;
- i = compacted.find('-', i))
- compacted.erase(i, 1);
-
- return compacted;
-}
-
-// A line-to-module loader that accepts line number info parsed by
-// dwarf2reader::LineInfo and populates a Module and a line vector
-// with the results.
-class DumpSymbols::DumperLineToModule:
- public DwarfCUToModule::LineToModuleHandler {
- public:
- // Create a line-to-module converter using BYTE_READER.
- DumperLineToModule(dwarf2reader::ByteReader *byte_reader)
- : byte_reader_(byte_reader) { }
-
- void StartCompilationUnit(const string& compilation_dir) {
- compilation_dir_ = compilation_dir;
- }
-
- void ReadProgram(const uint8_t *program, uint64 length,
- Module *module, vector<Module::Line> *lines) {
- DwarfLineToModule handler(module, compilation_dir_, lines);
- dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler);
- parser.Start();
- }
- private:
- string compilation_dir_;
- dwarf2reader::ByteReader *byte_reader_; // WEAK
-};
-
-bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
- // Select an object file, if SetArchitecture hasn't been called to set one
- // explicitly.
- if (!selected_object_file_) {
- // If there's only one architecture, that's the one.
- if (object_files_.size() == 1)
- selected_object_file_ = &object_files_[0];
- else {
- // Look for an object file whose architecture matches our own.
- const NXArchInfo *local_arch = NXGetLocalArchInfo();
- if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
- fprintf(stderr, "%s: object file contains more than one"
- " architecture, none of which match the current"
- " architecture; specify an architecture explicitly"
- " with '-a ARCH' to resolve the ambiguity\n",
- object_filename_.c_str());
- return false;
- }
- }
- }
-
- assert(selected_object_file_);
-
- // Find the name of the selected file's architecture, to appear in
- // the MODULE record and in error messages.
- const NXArchInfo *selected_arch_info =
- google_breakpad::BreakpadGetArchInfoFromCpuType(
- selected_object_file_->cputype, selected_object_file_->cpusubtype);
-
- const char *selected_arch_name = selected_arch_info->name;
- if (strcmp(selected_arch_name, "i386") == 0)
- selected_arch_name = "x86";
-
- // Produce a name to use in error messages that includes the
- // filename, and the architecture, if there is more than one.
- selected_object_name_ = object_filename_;
- if (object_files_.size() > 1) {
- selected_object_name_ += ", architecture ";
- selected_object_name_ + selected_arch_name;
- }
-
- // Compute a module name, to appear in the MODULE record.
- string module_name = object_filename_;
- module_name = basename(&module_name[0]);
-
- // Choose an identifier string, to appear in the MODULE record.
- string identifier = Identifier();
- if (identifier.empty())
- return false;
- identifier += "0";
-
- // Create a module to hold the debugging information.
- module.reset(new Module(module_name,
- "mac",
- selected_arch_name,
- identifier));
- return true;
-}
-
-bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
- const mach_o::Reader &macho_reader,
- const mach_o::SectionMap &dwarf_sections,
- bool handle_inter_cu_refs) const {
- // Build a byte reader of the appropriate endianness.
- ByteReader byte_reader(macho_reader.big_endian()
- ? dwarf2reader::ENDIANNESS_BIG
- : dwarf2reader::ENDIANNESS_LITTLE);
-
- // Construct a context for this file.
- DwarfCUToModule::FileContext file_context(selected_object_name_,
- module,
- handle_inter_cu_refs);
-
- // Build a dwarf2reader::SectionMap from our mach_o::SectionMap.
- for (mach_o::SectionMap::const_iterator it = dwarf_sections.begin();
- it != dwarf_sections.end(); ++it) {
- file_context.AddSectionToSectionMap(
- it->first,
- it->second.contents.start,
- it->second.contents.Size());
- }
-
- // Find the __debug_info section.
- dwarf2reader::SectionMap::const_iterator debug_info_entry =
- file_context.section_map().find("__debug_info");
- assert(debug_info_entry != file_context.section_map().end());
- const std::pair<const uint8_t *, uint64>& debug_info_section =
- debug_info_entry->second;
- // There had better be a __debug_info section!
- if (!debug_info_section.first) {
- fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n",
- selected_object_name_.c_str());
- return false;
- }
-
- // Build a line-to-module loader for the root handler to use.
- DumperLineToModule line_to_module(&byte_reader);
-
- // Walk the __debug_info section, one compilation unit at a time.
- uint64 debug_info_length = debug_info_section.second;
- for (uint64 offset = 0; offset < debug_info_length;) {
- // Make a handler for the root DIE that populates MODULE with the
- // debug info.
- DwarfCUToModule::WarningReporter reporter(selected_object_name_,
- offset);
- DwarfCUToModule root_handler(&file_context, &line_to_module, &reporter);
- // Make a Dwarf2Handler that drives our DIEHandler.
- dwarf2reader::DIEDispatcher die_dispatcher(&root_handler);
- // Make a DWARF parser for the compilation unit at OFFSET.
- dwarf2reader::CompilationUnit dwarf_reader(selected_object_name_,
- file_context.section_map(),
- offset,
- &byte_reader,
- &die_dispatcher);
- // Process the entire compilation unit; get the offset of the next.
- offset += dwarf_reader.Start();
- }
-
- return true;
-}
-
-bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
- const mach_o::Reader &macho_reader,
- const mach_o::Section &section,
- bool eh_frame) const {
- // Find the appropriate set of register names for this file's
- // architecture.
- vector<string> register_names;
- switch (macho_reader.cpu_type()) {
- case CPU_TYPE_X86:
- register_names = DwarfCFIToModule::RegisterNames::I386();
- break;
- case CPU_TYPE_X86_64:
- register_names = DwarfCFIToModule::RegisterNames::X86_64();
- break;
- case CPU_TYPE_ARM:
- register_names = DwarfCFIToModule::RegisterNames::ARM();
- break;
- case CPU_TYPE_ARM64:
- register_names = DwarfCFIToModule::RegisterNames::ARM64();
- break;
- default: {
- const NXArchInfo *arch = google_breakpad::BreakpadGetArchInfoFromCpuType(
- macho_reader.cpu_type(), macho_reader.cpu_subtype());
- fprintf(stderr, "%s: cannot convert DWARF call frame information for ",
- selected_object_name_.c_str());
- if (arch)
- fprintf(stderr, "architecture '%s'", arch->name);
- else
- fprintf(stderr, "architecture %d,%d",
- macho_reader.cpu_type(), macho_reader.cpu_subtype());
- fprintf(stderr, " to Breakpad symbol file: no register name table\n");
- return false;
- }
- }
-
- // Find the call frame information and its size.
- const uint8_t *cfi = section.contents.start;
- size_t cfi_size = section.contents.Size();
-
- // Plug together the parser, handler, and their entourages.
- DwarfCFIToModule::Reporter module_reporter(selected_object_name_,
- section.section_name);
- DwarfCFIToModule handler(module, register_names, &module_reporter);
- dwarf2reader::ByteReader byte_reader(macho_reader.big_endian() ?
- dwarf2reader::ENDIANNESS_BIG :
- dwarf2reader::ENDIANNESS_LITTLE);
- byte_reader.SetAddressSize(macho_reader.bits_64() ? 8 : 4);
- // At the moment, according to folks at Apple and some cursory
- // investigation, Mac OS X only uses DW_EH_PE_pcrel-based pointers, so
- // this is the only base address the CFI parser will need.
- byte_reader.SetCFIDataBase(section.address, cfi);
-
- dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(selected_object_name_,
- section.section_name);
- dwarf2reader::CallFrameInfo parser(cfi, cfi_size,
- &byte_reader, &handler, &dwarf_reporter,
- eh_frame);
- parser.Start();
- return true;
-}
-
-// A LoadCommandHandler that loads whatever debugging data it finds into a
-// Module.
-class DumpSymbols::LoadCommandDumper:
- public mach_o::Reader::LoadCommandHandler {
- public:
- // Create a load command dumper handling load commands from READER's
- // file, and adding data to MODULE.
- LoadCommandDumper(const DumpSymbols &dumper,
- google_breakpad::Module *module,
- const mach_o::Reader &reader,
- SymbolData symbol_data,
- bool handle_inter_cu_refs)
- : dumper_(dumper),
- module_(module),
- reader_(reader),
- symbol_data_(symbol_data),
- handle_inter_cu_refs_(handle_inter_cu_refs) { }
-
- bool SegmentCommand(const mach_o::Segment &segment);
- bool SymtabCommand(const ByteBuffer &entries, const ByteBuffer &strings);
-
- private:
- const DumpSymbols &dumper_;
- google_breakpad::Module *module_; // WEAK
- const mach_o::Reader &reader_;
- const SymbolData symbol_data_;
- const bool handle_inter_cu_refs_;
-};
-
-bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) {
- mach_o::SectionMap section_map;
- if (!reader_.MapSegmentSections(segment, &section_map))
- return false;
-
- if (segment.name == "__TEXT") {
- module_->SetLoadAddress(segment.vmaddr);
- if (symbol_data_ != NO_CFI) {
- mach_o::SectionMap::const_iterator eh_frame =
- section_map.find("__eh_frame");
- if (eh_frame != section_map.end()) {
- // If there is a problem reading this, don't treat it as a fatal error.
- dumper_.ReadCFI(module_, reader_, eh_frame->second, true);
- }
- }
- return true;
- }
-
- if (segment.name == "__DWARF") {
- if (symbol_data_ != ONLY_CFI) {
- if (!dumper_.ReadDwarf(module_, reader_, section_map,
- handle_inter_cu_refs_)) {
- return false;
- }
- }
- if (symbol_data_ != NO_CFI) {
- mach_o::SectionMap::const_iterator debug_frame
- = section_map.find("__debug_frame");
- if (debug_frame != section_map.end()) {
- // If there is a problem reading this, don't treat it as a fatal error.
- dumper_.ReadCFI(module_, reader_, debug_frame->second, false);
- }
- }
- }
-
- return true;
-}
-
-bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries,
- const ByteBuffer &strings) {
- StabsToModule stabs_to_module(module_);
- // Mac OS X STABS are never "unitized", and the size of the 'value' field
- // matches the address size of the executable.
- StabsReader stabs_reader(entries.start, entries.Size(),
- strings.start, strings.Size(),
- reader_.big_endian(),
- reader_.bits_64() ? 8 : 4,
- true,
- &stabs_to_module);
- if (!stabs_reader.Process())
- return false;
- stabs_to_module.Finalize();
- return true;
-}
-
-bool DumpSymbols::ReadSymbolData(Module** out_module) {
- scoped_ptr<Module> module;
- if (!CreateEmptyModule(module))
- return false;
-
- // Parse the selected object file.
- mach_o::Reader::Reporter reporter(selected_object_name_);
- mach_o::Reader reader(&reporter);
- if (!reader.Read(&contents_[0]
- + selected_object_file_->offset,
- selected_object_file_->size,
- selected_object_file_->cputype,
- selected_object_file_->cpusubtype))
- return false;
-
- // Walk its load commands, and deal with whatever is there.
- LoadCommandDumper load_command_dumper(*this, module.get(), reader,
- symbol_data_, handle_inter_cu_refs_);
- if (!reader.WalkLoadCommands(&load_command_dumper))
- return false;
-
- *out_module = module.release();
-
- return true;
-}
-
-bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
- Module* module = NULL;
-
- if (ReadSymbolData(&module) && module) {
- bool res = module->Write(stream, symbol_data_);
- delete module;
- return res;
- }
-
- return false;
-}
-
-// Read the selected object file's debugging information, and write out the
-// header only to |stream|. Return true on success; if an error occurs, report
-// it and return false.
-bool DumpSymbols::WriteSymbolFileHeader(std::ostream &stream) {
- scoped_ptr<Module> module;
- if (!CreateEmptyModule(module))
- return false;
-
- return module->Write(stream, symbol_data_);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h b/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
deleted file mode 100644
index 9463f7dc0..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/dump_syms.h
+++ /dev/null
@@ -1,196 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_syms.h: Declaration of google_breakpad::DumpSymbols, a class for
-// reading debugging information from Mach-O files and writing it out as a
-// Breakpad symbol file.
-
-#include <mach-o/loader.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "common/byte_cursor.h"
-#include "common/mac/macho_reader.h"
-#include "common/mac/super_fat_arch.h"
-#include "common/module.h"
-#include "common/scoped_ptr.h"
-#include "common/symbol_data.h"
-
-namespace google_breakpad {
-
-class DumpSymbols {
- public:
- DumpSymbols(SymbolData symbol_data, bool handle_inter_cu_refs)
- : symbol_data_(symbol_data),
- handle_inter_cu_refs_(handle_inter_cu_refs),
- input_pathname_(),
- object_filename_(),
- contents_(),
- object_files_(),
- selected_object_file_(),
- selected_object_name_() { }
- ~DumpSymbols() {
- }
-
- // Prepare to read debugging information from |filename|. |filename| may be
- // the name of a universal binary, a Mach-O file, or a dSYM bundle
- // containing either of the above. On success, return true; if there is a
- // problem reading |filename|, report it and return false.
- bool Read(const std::string &filename);
-
- // If this dumper's file includes an object file for |cpu_type| and
- // |cpu_subtype|, then select that object file for dumping, and return
- // true. Otherwise, return false, and leave this dumper's selected
- // architecture unchanged.
- //
- // By default, if this dumper's file contains only one object file, then
- // the dumper will dump those symbols; and if it contains more than one
- // object file, then the dumper will dump the object file whose
- // architecture matches that of this dumper program.
- bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
-
- // If this dumper's file includes an object file for |arch_name|, then select
- // that object file for dumping, and return true. Otherwise, return false,
- // and leave this dumper's selected architecture unchanged.
- //
- // By default, if this dumper's file contains only one object file, then
- // the dumper will dump those symbols; and if it contains more than one
- // object file, then the dumper will dump the object file whose
- // architecture matches that of this dumper program.
- bool SetArchitecture(const std::string &arch_name);
-
- // Return a pointer to an array of SuperFatArch structures describing the
- // object files contained in this dumper's file. Set *|count| to the number
- // of elements in the array. The returned array is owned by this DumpSymbols
- // instance.
- //
- // If there are no available architectures, this function
- // may return NULL.
- const SuperFatArch* AvailableArchitectures(size_t *count) {
- *count = object_files_.size();
- if (object_files_.size() > 0)
- return &object_files_[0];
- return NULL;
- }
-
- // Read the selected object file's debugging information, and write it out to
- // |stream|. Return true on success; if an error occurs, report it and
- // return false.
- bool WriteSymbolFile(std::ostream &stream);
-
- // Read the selected object file's debugging information, and write out the
- // header only to |stream|. Return true on success; if an error occurs, report
- // it and return false.
- bool WriteSymbolFileHeader(std::ostream &stream);
-
- // As above, but simply return the debugging information in module
- // instead of writing it to a stream. The caller owns the resulting
- // module object and must delete it when finished.
- bool ReadSymbolData(Module** module);
-
- private:
- // Used internally.
- class DumperLineToModule;
- class LoadCommandDumper;
-
- // This method behaves similarly to NXFindBestFatArch, but it supports
- // SuperFatArch.
- SuperFatArch* FindBestMatchForArchitecture(
- cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
-
- // Return an identifier string for the file this DumpSymbols is dumping.
- std::string Identifier();
-
-
- // Creates an empty module object.
- bool CreateEmptyModule(scoped_ptr<Module>& module);
-
- // Read debugging information from |dwarf_sections|, which was taken from
- // |macho_reader|, and add it to |module|. On success, return true;
- // on failure, report the problem and return false.
- bool ReadDwarf(google_breakpad::Module *module,
- const mach_o::Reader &macho_reader,
- const mach_o::SectionMap &dwarf_sections,
- bool handle_inter_cu_refs) const;
-
- // Read DWARF CFI or .eh_frame data from |section|, belonging to
- // |macho_reader|, and record it in |module|. If |eh_frame| is true,
- // then the data is .eh_frame-format data; otherwise, it is standard DWARF
- // .debug_frame data. On success, return true; on failure, report
- // the problem and return false.
- bool ReadCFI(google_breakpad::Module *module,
- const mach_o::Reader &macho_reader,
- const mach_o::Section &section,
- bool eh_frame) const;
-
- // The selection of what type of symbol data to read/write.
- const SymbolData symbol_data_;
-
- // Whether to handle references between compilation units.
- const bool handle_inter_cu_refs_;
-
- // The name of the file or bundle whose symbols this will dump.
- // This is the path given to Read, for use in error messages.
- std::string input_pathname_;
-
- // The name of the file this DumpSymbols will actually read debugging
- // information from. Normally, this is the same as input_pathname_, but if
- // filename refers to a dSYM bundle, then this is the resource file
- // within that bundle.
- std::string object_filename_;
-
- // The complete contents of object_filename_, mapped into memory.
- scoped_array<uint8_t> contents_;
-
- // A vector of SuperFatArch structures describing the object files
- // object_filename_ contains. If object_filename_ refers to a fat binary,
- // this may have more than one element; if it refers to a Mach-O file, this
- // has exactly one element.
- vector<SuperFatArch> object_files_;
-
- // The object file in object_files_ selected to dump, or NULL if
- // SetArchitecture hasn't been called yet.
- const SuperFatArch *selected_object_file_;
-
- // A string that identifies the selected object file, for use in error
- // messages. This is usually object_filename_, but if that refers to a
- // fat binary, it includes an indication of the particular architecture
- // within that binary.
- string selected_object_name_;
-};
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc
deleted file mode 100644
index 4661d5d62..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// file_id.cc: Return a unique identifier for a file
-//
-// See file_id.h for documentation
-//
-// Author: Dan Waylonis
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "common/mac/file_id.h"
-#include "common/mac/macho_id.h"
-
-using MacFileUtilities::MachoID;
-
-namespace google_breakpad {
-
-FileID::FileID(const char *path) {
- snprintf(path_, sizeof(path_), "%s", path);
-}
-
-bool FileID::FileIdentifier(unsigned char identifier[16]) {
- int fd = open(path_, O_RDONLY);
- if (fd == -1)
- return false;
-
- MD5Context md5;
- MD5Init(&md5);
-
- // Read 4k x 2 bytes at a time. This is faster than just 4k bytes, but
- // doesn't seem to be an unreasonable size for the stack.
- unsigned char buffer[4096 * 2];
- size_t buffer_size = sizeof(buffer);
- while ((buffer_size = read(fd, buffer, buffer_size) > 0)) {
- MD5Update(&md5, buffer, static_cast<unsigned>(buffer_size));
- }
-
- close(fd);
- MD5Final(identifier, &md5);
-
- return true;
-}
-
-bool FileID::MachoIdentifier(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]) {
- MachoID macho(path_);
-
- if (macho.UUIDCommand(cpu_type, cpu_subtype, identifier))
- return true;
-
- return macho.MD5(cpu_type, cpu_subtype, identifier);
-}
-
-// static
-void FileID::ConvertIdentifierToString(const unsigned char identifier[16],
- char *buffer, int buffer_length) {
- int buffer_idx = 0;
- for (int idx = 0; (buffer_idx < buffer_length) && (idx < 16); ++idx) {
- int hi = (identifier[idx] >> 4) & 0x0F;
- int lo = (identifier[idx]) & 0x0F;
-
- if (idx == 4 || idx == 6 || idx == 8 || idx == 10)
- buffer[buffer_idx++] = '-';
-
- buffer[buffer_idx++] =
- static_cast<char>((hi >= 10) ? ('A' + hi - 10) : ('0' + hi));
- buffer[buffer_idx++] =
- static_cast<char>((lo >= 10) ? ('A' + lo - 10) : ('0' + lo));
- }
-
- // NULL terminate
- buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h
deleted file mode 100644
index 1d6dfde1b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/file_id.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// file_id.h: Return a unique identifier for a file
-//
-// Author: Dan Waylonis
-
-#ifndef COMMON_MAC_FILE_ID_H__
-#define COMMON_MAC_FILE_ID_H__
-
-#include <limits.h>
-#include <mach/machine.h>
-
-namespace google_breakpad {
-
-class FileID {
- public:
- FileID(const char *path);
- ~FileID() {};
-
- // Load the identifier for the file path specified in the constructor into
- // |identifier|. Return false if the identifier could not be created for the
- // file.
- // The current implementation will return the MD5 hash of the file's bytes.
- bool FileIdentifier(unsigned char identifier[16]);
-
- // Treat the file as a mach-o file that will contain one or more archicture.
- // Accepted values for |cpu_type| and |cpu_subtype| (e.g., CPU_TYPE_X86 or
- // CPU_TYPE_POWERPC) are listed in /usr/include/mach/machine.h.
- // If |cpu_type| is 0, then the native cpu type is used. If |cpu_subtype| is
- // CPU_SUBTYPE_MULTIPLE, the match is only done on |cpu_type|.
- // Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype|
- // is not present in the file.
- // Return the unique identifier in |identifier|.
- // The current implementation will look for the (in order of priority):
- // LC_UUID, LC_ID_DYLIB, or MD5 hash of the given |cpu_type|.
- bool MachoIdentifier(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]);
-
- // Convert the |identifier| data to a NULL terminated string. The string will
- // be formatted as a UUID (e.g., 22F065BB-FC9C-49F7-80FE-26A7CEBD7BCE).
- // The |buffer| should be at least 37 bytes long to receive all of the data
- // and termination. Shorter buffers will contain truncated data.
- static void ConvertIdentifierToString(const unsigned char identifier[16],
- char *buffer, int buffer_length);
-
- private:
- // Storage for the path specified
- char path_[PATH_MAX];
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_MAC_FILE_ID_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc
deleted file mode 100644
index 245be8265..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2014, 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 <stdio.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-namespace google_breakpad {
-
-void LaunchReporter(const char *reporter_executable_path,
- const char *config_file_path) {
- const char* argv[] = { reporter_executable_path, config_file_path, NULL };
-
- // Launch the reporter
- pid_t pid = fork();
-
- if (pid == -1) {
- perror("fork");
- fprintf(stderr, "Failed to fork reporter process\n");
- return;
- }
-
- // If we're in the child, load in our new executable and run.
- // The parent will not wait for the child to complete.
- if (pid == 0) {
- execv(argv[0], (char* const*)argv);
- perror("exec");
- fprintf(stderr,
- "Failed to launch reporter process from path %s\n",
- reporter_executable_path);
- unlink(config_file_path); // launch failed - get rid of config file
- _exit(1);
- }
-
- // Wait until the Reporter child process exits.
- //
-
- // We'll use a timeout of one minute.
- int timeout_count = 60; // 60 seconds
-
- while (timeout_count-- > 0) {
- int status;
- pid_t result = waitpid(pid, &status, WNOHANG);
-
- if (result == 0) {
- // The child has not yet finished.
- sleep(1);
- } else if (result == -1) {
- // error occurred.
- break;
- } else {
- // child has finished
- break;
- }
- }
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h b/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h
deleted file mode 100644
index 4531123c2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/launch_reporter.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2014, 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 COMMON_MAC_LAUNCH_REPORTER_H__
-#define COMMON_MAC_LAUNCH_REPORTER_H__
-
-namespace google_breakpad {
-
-// Launch the crash dump sender app.
-// |reporter_executable_path| is the path to the sender executable.
-// |config_file_path| is the path to the config file.
-void LaunchReporter(const char *reporter_executable_path,
- const char *config_file_path);
-
-} // namespace google_breakpad
-
-#endif // COMMON_MAC_LAUNCH_REPORTER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc
deleted file mode 100644
index c396ad888..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.cc
+++ /dev/null
@@ -1,369 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_id.cc: Functions to gather identifying information from a macho file
-//
-// See macho_id.h for documentation
-//
-// Author: Dan Waylonis
-
-
-#include <fcntl.h>
-#include <mach-o/loader.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "common/mac/macho_id.h"
-#include "common/mac/macho_walker.h"
-#include "common/mac/macho_utilities.h"
-
-namespace MacFileUtilities {
-
-using google_breakpad::MD5Init;
-using google_breakpad::MD5Update;
-using google_breakpad::MD5Final;
-
-MachoID::MachoID(const char *path)
- : memory_(0),
- memory_size_(0),
- crc_(0),
- md5_context_(),
- update_function_(NULL) {
- snprintf(path_, sizeof(path_), "%s", path);
-}
-
-MachoID::MachoID(const char *path, void *memory, size_t size)
- : memory_(memory),
- memory_size_(size),
- crc_(0),
- md5_context_(),
- update_function_(NULL) {
- snprintf(path_, sizeof(path_), "%s", path);
-}
-
-MachoID::~MachoID() {
-}
-
-// The CRC info is from http://en.wikipedia.org/wiki/Adler-32
-// With optimizations from http://www.zlib.net/
-
-// The largest prime smaller than 65536
-#define MOD_ADLER 65521
-// MAX_BLOCK is the largest n such that 255n(n+1)/2 + (n+1)(MAX_BLOCK-1) <= 2^32-1
-#define MAX_BLOCK 5552
-
-void MachoID::UpdateCRC(unsigned char *bytes, size_t size) {
-// Unrolled loops for summing
-#define DO1(buf,i) {sum1 += (buf)[i]; sum2 += sum1;}
-#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf) DO8(buf,0); DO8(buf,8);
- // Split up the crc
- uint32_t sum1 = crc_ & 0xFFFF;
- uint32_t sum2 = (crc_ >> 16) & 0xFFFF;
-
- // Do large blocks
- while (size >= MAX_BLOCK) {
- size -= MAX_BLOCK;
- int block_count = MAX_BLOCK / 16;
- do {
- DO16(bytes);
- bytes += 16;
- } while (--block_count);
- sum1 %= MOD_ADLER;
- sum2 %= MOD_ADLER;
- }
-
- // Do remaining bytes
- if (size) {
- while (size >= 16) {
- size -= 16;
- DO16(bytes);
- bytes += 16;
- }
- while (size--) {
- sum1 += *bytes++;
- sum2 += sum1;
- }
- sum1 %= MOD_ADLER;
- sum2 %= MOD_ADLER;
- crc_ = (sum2 << 16) | sum1;
- }
-}
-
-void MachoID::UpdateMD5(unsigned char *bytes, size_t size) {
- MD5Update(&md5_context_, bytes, static_cast<unsigned>(size));
-}
-
-void MachoID::Update(MachoWalker *walker, off_t offset, size_t size) {
- if (!update_function_ || !size)
- return;
-
- // Read up to 4k bytes at a time
- unsigned char buffer[4096];
- size_t buffer_size;
- off_t file_offset = offset;
- while (size > 0) {
- if (size > sizeof(buffer)) {
- buffer_size = sizeof(buffer);
- size -= buffer_size;
- } else {
- buffer_size = size;
- size = 0;
- }
-
- if (!walker->ReadBytes(buffer, buffer_size, file_offset))
- return;
-
- (this->*update_function_)(buffer, buffer_size);
- file_offset += buffer_size;
- }
-}
-
-bool MachoID::UUIDCommand(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char bytes[16]) {
- struct breakpad_uuid_command uuid_cmd;
- uuid_cmd.cmd = 0;
- if (!WalkHeader(cpu_type, cpu_subtype, UUIDWalkerCB, &uuid_cmd))
- return false;
-
- // If we found the command, we'll have initialized the uuid_command
- // structure
- if (uuid_cmd.cmd == LC_UUID) {
- memcpy(bytes, uuid_cmd.uuid, sizeof(uuid_cmd.uuid));
- return true;
- }
-
- return false;
-}
-
-bool MachoID::IDCommand(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]) {
- struct dylib_command dylib_cmd;
- dylib_cmd.cmd = 0;
- if (!WalkHeader(cpu_type, cpu_subtype, IDWalkerCB, &dylib_cmd))
- return false;
-
- // If we found the command, we'll have initialized the dylib_command
- // structure
- if (dylib_cmd.cmd == LC_ID_DYLIB) {
- // Take the hashed filename, version, and compatability version bytes
- // to form the first 12 bytes, pad the rest with zeros
-
- // create a crude hash of the filename to generate the first 4 bytes
- identifier[0] = 0;
- identifier[1] = 0;
- identifier[2] = 0;
- identifier[3] = 0;
-
- for (int j = 0, i = (int)strlen(path_)-1; i>=0 && path_[i]!='/'; ++j, --i) {
- identifier[j%4] += path_[i];
- }
-
- identifier[4] = (dylib_cmd.dylib.current_version >> 24) & 0xFF;
- identifier[5] = (dylib_cmd.dylib.current_version >> 16) & 0xFF;
- identifier[6] = (dylib_cmd.dylib.current_version >> 8) & 0xFF;
- identifier[7] = dylib_cmd.dylib.current_version & 0xFF;
- identifier[8] = (dylib_cmd.dylib.compatibility_version >> 24) & 0xFF;
- identifier[9] = (dylib_cmd.dylib.compatibility_version >> 16) & 0xFF;
- identifier[10] = (dylib_cmd.dylib.compatibility_version >> 8) & 0xFF;
- identifier[11] = dylib_cmd.dylib.compatibility_version & 0xFF;
- identifier[12] = (cpu_type >> 24) & 0xFF;
- identifier[13] = (cpu_type >> 16) & 0xFF;
- identifier[14] = (cpu_type >> 8) & 0xFF;
- identifier[15] = cpu_type & 0xFF;
-
- return true;
- }
-
- return false;
-}
-
-uint32_t MachoID::Adler32(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
- update_function_ = &MachoID::UpdateCRC;
- crc_ = 0;
-
- if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this))
- return 0;
-
- return crc_;
-}
-
-bool MachoID::MD5(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype, unsigned char identifier[16]) {
- update_function_ = &MachoID::UpdateMD5;
-
- MD5Init(&md5_context_);
-
- if (!WalkHeader(cpu_type, cpu_subtype, WalkerCB, this))
- return false;
-
- MD5Final(identifier, &md5_context_);
- return true;
-}
-
-bool MachoID::WalkHeader(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- MachoWalker::LoadCommandCallback callback,
- void *context) {
- if (memory_) {
- MachoWalker walker(memory_, memory_size_, callback, context);
- return walker.WalkHeader(cpu_type, cpu_subtype);
- } else {
- MachoWalker walker(path_, callback, context);
- return walker.WalkHeader(cpu_type, cpu_subtype);
- }
-}
-
-// static
-bool MachoID::WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context) {
- MachoID *macho_id = (MachoID *)context;
-
- if (cmd->cmd == LC_SEGMENT) {
- struct segment_command seg;
-
- if (!walker->ReadBytes(&seg, sizeof(seg), offset))
- return false;
-
- if (swap)
- breakpad_swap_segment_command(&seg);
-
- struct mach_header_64 header;
- off_t header_offset;
-
- if (!walker->CurrentHeader(&header, &header_offset))
- return false;
-
- // Process segments that have sections:
- // (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
- offset += sizeof(struct segment_command);
- struct section sec;
- for (unsigned long i = 0; i < seg.nsects; ++i) {
- if (!walker->ReadBytes(&sec, sizeof(sec), offset))
- return false;
-
- if (swap)
- breakpad_swap_section(&sec, 1);
-
- // sections of type S_ZEROFILL are "virtual" and contain no data
- // in the file itself
- if ((sec.flags & SECTION_TYPE) != S_ZEROFILL && sec.offset != 0)
- macho_id->Update(walker, header_offset + sec.offset, sec.size);
-
- offset += sizeof(struct section);
- }
- } else if (cmd->cmd == LC_SEGMENT_64) {
- struct segment_command_64 seg64;
-
- if (!walker->ReadBytes(&seg64, sizeof(seg64), offset))
- return false;
-
- if (swap)
- breakpad_swap_segment_command_64(&seg64);
-
- struct mach_header_64 header;
- off_t header_offset;
-
- if (!walker->CurrentHeader(&header, &header_offset))
- return false;
-
- // Process segments that have sections:
- // (e.g., __TEXT, __DATA, __IMPORT, __OBJC)
- offset += sizeof(struct segment_command_64);
- struct section_64 sec64;
- for (unsigned long i = 0; i < seg64.nsects; ++i) {
- if (!walker->ReadBytes(&sec64, sizeof(sec64), offset))
- return false;
-
- if (swap)
- breakpad_swap_section_64(&sec64, 1);
-
- // sections of type S_ZEROFILL are "virtual" and contain no data
- // in the file itself
- if ((sec64.flags & SECTION_TYPE) != S_ZEROFILL && sec64.offset != 0)
- macho_id->Update(walker,
- header_offset + sec64.offset,
- (size_t)sec64.size);
-
- offset += sizeof(struct section_64);
- }
- }
-
- // Continue processing
- return true;
-}
-
-// static
-bool MachoID::UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context) {
- if (cmd->cmd == LC_UUID) {
- struct breakpad_uuid_command *uuid_cmd =
- (struct breakpad_uuid_command *)context;
-
- if (!walker->ReadBytes(uuid_cmd, sizeof(struct breakpad_uuid_command),
- offset))
- return false;
-
- if (swap)
- breakpad_swap_uuid_command(uuid_cmd);
-
- return false;
- }
-
- // Continue processing
- return true;
-}
-
-// static
-bool MachoID::IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context) {
- if (cmd->cmd == LC_ID_DYLIB) {
- struct dylib_command *dylib_cmd = (struct dylib_command *)context;
-
- if (!walker->ReadBytes(dylib_cmd, sizeof(struct dylib_command), offset))
- return false;
-
- if (swap)
- breakpad_swap_dylib_command(dylib_cmd);
-
- return false;
- }
-
- // Continue processing
- return true;
-}
-
-} // namespace MacFileUtilities
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h
deleted file mode 100644
index 103754912..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_id.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_id.h: Functions to gather identifying information from a macho file
-//
-// Author: Dan Waylonis
-
-#ifndef COMMON_MAC_MACHO_ID_H__
-#define COMMON_MAC_MACHO_ID_H__
-
-#include <limits.h>
-#include <mach/machine.h>
-#include <mach-o/loader.h>
-
-#include "common/mac/macho_walker.h"
-#include "common/md5.h"
-
-namespace MacFileUtilities {
-
-class MachoID {
- public:
- MachoID(const char *path);
- MachoID(const char *path, void *memory, size_t size);
- ~MachoID();
-
- // For the given |cpu_type| and |cpu_subtype|, return a UUID from the LC_UUID
- // command.
- // Return false if there isn't a LC_UUID command.
- bool UUIDCommand(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]);
-
- // For the given |cpu_type| and |cpu_subtype|, return a UUID from the
- // LC_ID_DYLIB command.
- // Return false if there isn't a LC_ID_DYLIB command.
- bool IDCommand(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]);
-
- // For the given |cpu_type| and |cpu_subtype|, return the Adler32 CRC for the
- // mach-o data segment(s).
- // Return 0 on error (e.g., if the file is not a mach-o file)
- uint32_t Adler32(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype);
-
- // For the given |cpu_type|, and |cpu_subtype| return the MD5 for the mach-o
- // data segment(s).
- // Return true on success, false otherwise
- bool MD5(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- unsigned char identifier[16]);
-
- private:
- // Signature of class member function to be called with data read from file
- typedef void (MachoID::*UpdateFunction)(unsigned char *bytes, size_t size);
-
- // Update the CRC value by examining |size| |bytes| and applying the algorithm
- // to each byte.
- void UpdateCRC(unsigned char *bytes, size_t size);
-
- // Update the MD5 value by examining |size| |bytes| and applying the algorithm
- // to each byte.
- void UpdateMD5(unsigned char *bytes, size_t size);
-
- // Bottleneck for update routines
- void Update(MachoWalker *walker, off_t offset, size_t size);
-
- // Factory for the MachoWalker
- bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype,
- MachoWalker::LoadCommandCallback callback, void *context);
-
- // The callback from the MachoWalker for CRC and MD5
- static bool WalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context);
-
- // The callback from the MachoWalker for LC_UUID
- static bool UUIDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context);
-
- // The callback from the MachoWalker for LC_ID_DYLIB
- static bool IDWalkerCB(MachoWalker *walker, load_command *cmd, off_t offset,
- bool swap, void *context);
-
- // File path
- char path_[PATH_MAX];
-
- // Memory region to read from
- void *memory_;
-
- // Size of the memory region
- size_t memory_size_;
-
- // The current crc value
- uint32_t crc_;
-
- // The MD5 context
- google_breakpad::MD5Context md5_context_;
-
- // The current update to call from the Update callback
- UpdateFunction update_function_;
-};
-
-} // namespace MacFileUtilities
-
-#endif // COMMON_MAC_MACHO_ID_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc
deleted file mode 100644
index 52f3c411b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.cc
+++ /dev/null
@@ -1,539 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// macho_reader.cc: Implementation of google_breakpad::Mach_O::FatReader and
-// google_breakpad::Mach_O::Reader. See macho_reader.h for details.
-
-#include "common/mac/macho_reader.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-// Unfortunately, CPU_TYPE_ARM is not define for 10.4.
-#if !defined(CPU_TYPE_ARM)
-#define CPU_TYPE_ARM 12
-#endif
-
-#if !defined(CPU_TYPE_ARM_64)
-#define CPU_TYPE_ARM_64 16777228
-#endif
-
-namespace google_breakpad {
-namespace mach_o {
-
-// If NDEBUG is #defined, then the 'assert' macro doesn't evaluate its
-// arguments, so you can't place expressions that do necessary work in
-// the argument of an assert. Nor can you assign the result of the
-// expression to a variable and assert that the variable's value is
-// true: you'll get unused variable warnings when NDEBUG is #defined.
-//
-// ASSERT_ALWAYS_EVAL always evaluates its argument, and asserts that
-// the result is true if NDEBUG is not #defined.
-#if defined(NDEBUG)
-#define ASSERT_ALWAYS_EVAL(x) (x)
-#else
-#define ASSERT_ALWAYS_EVAL(x) assert(x)
-#endif
-
-void FatReader::Reporter::BadHeader() {
- fprintf(stderr, "%s: file is neither a fat binary file"
- " nor a Mach-O object file\n", filename_.c_str());
-}
-
-void FatReader::Reporter::TooShort() {
- fprintf(stderr, "%s: file too short for the data it claims to contain\n",
- filename_.c_str());
-}
-
-void FatReader::Reporter::MisplacedObjectFile() {
- fprintf(stderr, "%s: file too short for the object files it claims"
- " to contain\n", filename_.c_str());
-}
-
-bool FatReader::Read(const uint8_t *buffer, size_t size) {
- buffer_.start = buffer;
- buffer_.end = buffer + size;
- ByteCursor cursor(&buffer_);
-
- // Fat binaries always use big-endian, so read the magic number in
- // that endianness. To recognize Mach-O magic numbers, which can use
- // either endianness, check for both the proper and reversed forms
- // of the magic numbers.
- cursor.set_big_endian(true);
- if (cursor >> magic_) {
- if (magic_ == FAT_MAGIC) {
- // How many object files does this fat binary contain?
- uint32_t object_files_count;
- if (!(cursor >> object_files_count)) { // nfat_arch
- reporter_->TooShort();
- return false;
- }
-
- // Read the list of object files.
- object_files_.resize(object_files_count);
- for (size_t i = 0; i < object_files_count; i++) {
- struct fat_arch objfile;
-
- // Read this object file entry, byte-swapping as appropriate.
- cursor >> objfile.cputype
- >> objfile.cpusubtype
- >> objfile.offset
- >> objfile.size
- >> objfile.align;
-
- SuperFatArch super_fat_arch(objfile);
- object_files_[i] = super_fat_arch;
-
- if (!cursor) {
- reporter_->TooShort();
- return false;
- }
- // Does the file actually have the bytes this entry refers to?
- size_t fat_size = buffer_.Size();
- if (objfile.offset > fat_size ||
- objfile.size > fat_size - objfile.offset) {
- reporter_->MisplacedObjectFile();
- return false;
- }
- }
-
- return true;
- } else if (magic_ == MH_MAGIC || magic_ == MH_MAGIC_64 ||
- magic_ == MH_CIGAM || magic_ == MH_CIGAM_64) {
- // If this is a little-endian Mach-O file, fix the cursor's endianness.
- if (magic_ == MH_CIGAM || magic_ == MH_CIGAM_64)
- cursor.set_big_endian(false);
- // Record the entire file as a single entry in the object file list.
- object_files_.resize(1);
-
- // Get the cpu type and subtype from the Mach-O header.
- if (!(cursor >> object_files_[0].cputype
- >> object_files_[0].cpusubtype)) {
- reporter_->TooShort();
- return false;
- }
-
- object_files_[0].offset = 0;
- object_files_[0].size = static_cast<uint64_t>(buffer_.Size());
- // This alignment is correct for 32 and 64-bit x86 and ppc.
- // See get_align in the lipo source for other architectures:
- // http://www.opensource.apple.com/source/cctools/cctools-773/misc/lipo.c
- object_files_[0].align = 12; // 2^12 == 4096
- return true;
- }
- }
- reporter_->BadHeader();
- return false;
-}
-
-void Reader::Reporter::BadHeader() {
- fprintf(stderr, "%s: file is not a Mach-O object file\n", filename_.c_str());
-}
-
-void Reader::Reporter::CPUTypeMismatch(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype) {
- fprintf(stderr, "%s: CPU type %d, subtype %d does not match expected"
- " type %d, subtype %d\n",
- filename_.c_str(), cpu_type, cpu_subtype,
- expected_cpu_type, expected_cpu_subtype);
-}
-
-void Reader::Reporter::HeaderTruncated() {
- fprintf(stderr, "%s: file does not contain a complete Mach-O header\n",
- filename_.c_str());
-}
-
-void Reader::Reporter::LoadCommandRegionTruncated() {
- fprintf(stderr, "%s: file too short to hold load command region"
- " given in Mach-O header\n", filename_.c_str());
-}
-
-void Reader::Reporter::LoadCommandsOverrun(size_t claimed, size_t i,
- LoadCommandType type) {
- fprintf(stderr, "%s: file's header claims there are %zu"
- " load commands, but load command #%zu",
- filename_.c_str(), claimed, i);
- if (type) fprintf(stderr, ", of type %d,", type);
- fprintf(stderr, " extends beyond the end of the load command region\n");
-}
-
-void Reader::Reporter::LoadCommandTooShort(size_t i, LoadCommandType type) {
- fprintf(stderr, "%s: the contents of load command #%zu, of type %d,"
- " extend beyond the size given in the load command's header\n",
- filename_.c_str(), i, type);
-}
-
-void Reader::Reporter::SectionsMissing(const string &name) {
- fprintf(stderr, "%s: the load command for segment '%s'"
- " is too short to hold the section headers it claims to have\n",
- filename_.c_str(), name.c_str());
-}
-
-void Reader::Reporter::MisplacedSegmentData(const string &name) {
- fprintf(stderr, "%s: the segment '%s' claims its contents lie beyond"
- " the end of the file\n", filename_.c_str(), name.c_str());
-}
-
-void Reader::Reporter::MisplacedSectionData(const string &section,
- const string &segment) {
- fprintf(stderr, "%s: the section '%s' in segment '%s'"
- " claims its contents lie outside the segment's contents\n",
- filename_.c_str(), section.c_str(), segment.c_str());
-}
-
-void Reader::Reporter::MisplacedSymbolTable() {
- fprintf(stderr, "%s: the LC_SYMTAB load command claims that the symbol"
- " table's contents are located beyond the end of the file\n",
- filename_.c_str());
-}
-
-void Reader::Reporter::UnsupportedCPUType(cpu_type_t cpu_type) {
- fprintf(stderr, "%s: CPU type %d is not supported\n",
- filename_.c_str(), cpu_type);
-}
-
-bool Reader::Read(const uint8_t *buffer,
- size_t size,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype) {
- assert(!buffer_.start);
- buffer_.start = buffer;
- buffer_.end = buffer + size;
- ByteCursor cursor(&buffer_, true);
- uint32_t magic;
- if (!(cursor >> magic)) {
- reporter_->HeaderTruncated();
- return false;
- }
-
- if (expected_cpu_type != CPU_TYPE_ANY) {
- uint32_t expected_magic;
- // validate that magic matches the expected cpu type
- switch (expected_cpu_type) {
- case CPU_TYPE_ARM:
- case CPU_TYPE_I386:
- expected_magic = MH_CIGAM;
- break;
- case CPU_TYPE_POWERPC:
- expected_magic = MH_MAGIC;
- break;
- case CPU_TYPE_ARM_64:
- case CPU_TYPE_X86_64:
- expected_magic = MH_CIGAM_64;
- break;
- case CPU_TYPE_POWERPC64:
- expected_magic = MH_MAGIC_64;
- break;
- default:
- reporter_->UnsupportedCPUType(expected_cpu_type);
- return false;
- }
-
- if (expected_magic != magic) {
- reporter_->BadHeader();
- return false;
- }
- }
-
- // Since the byte cursor is in big-endian mode, a reversed magic number
- // always indicates a little-endian file, regardless of our own endianness.
- switch (magic) {
- case MH_MAGIC: big_endian_ = true; bits_64_ = false; break;
- case MH_CIGAM: big_endian_ = false; bits_64_ = false; break;
- case MH_MAGIC_64: big_endian_ = true; bits_64_ = true; break;
- case MH_CIGAM_64: big_endian_ = false; bits_64_ = true; break;
- default:
- reporter_->BadHeader();
- return false;
- }
- cursor.set_big_endian(big_endian_);
- uint32_t commands_size, reserved;
- cursor >> cpu_type_ >> cpu_subtype_ >> file_type_ >> load_command_count_
- >> commands_size >> flags_;
- if (bits_64_)
- cursor >> reserved;
- if (!cursor) {
- reporter_->HeaderTruncated();
- return false;
- }
-
- if (expected_cpu_type != CPU_TYPE_ANY &&
- (expected_cpu_type != cpu_type_ ||
- expected_cpu_subtype != cpu_subtype_)) {
- reporter_->CPUTypeMismatch(cpu_type_, cpu_subtype_,
- expected_cpu_type, expected_cpu_subtype);
- return false;
- }
-
- cursor
- .PointTo(&load_commands_.start, commands_size)
- .PointTo(&load_commands_.end, 0);
- if (!cursor) {
- reporter_->LoadCommandRegionTruncated();
- return false;
- }
-
- return true;
-}
-
-bool Reader::WalkLoadCommands(Reader::LoadCommandHandler *handler) const {
- ByteCursor list_cursor(&load_commands_, big_endian_);
-
- for (size_t index = 0; index < load_command_count_; ++index) {
- // command refers to this load command alone, so that cursor will
- // refuse to read past the load command's end. But since we haven't
- // read the size yet, let command initially refer to the entire
- // remainder of the load command series.
- ByteBuffer command(list_cursor.here(), list_cursor.Available());
- ByteCursor cursor(&command, big_endian_);
-
- // Read the command type and size --- fields common to all commands.
- uint32_t type, size;
- if (!(cursor >> type)) {
- reporter_->LoadCommandsOverrun(load_command_count_, index, 0);
- return false;
- }
- if (!(cursor >> size) || size > command.Size()) {
- reporter_->LoadCommandsOverrun(load_command_count_, index, type);
- return false;
- }
-
- // Now that we've read the length, restrict command's range to this
- // load command only.
- command.end = command.start + size;
-
- switch (type) {
- case LC_SEGMENT:
- case LC_SEGMENT_64: {
- Segment segment;
- segment.bits_64 = (type == LC_SEGMENT_64);
- size_t word_size = segment.bits_64 ? 8 : 4;
- cursor.CString(&segment.name, 16);
- size_t file_offset, file_size;
- cursor
- .Read(word_size, false, &segment.vmaddr)
- .Read(word_size, false, &segment.vmsize)
- .Read(word_size, false, &file_offset)
- .Read(word_size, false, &file_size);
- cursor >> segment.maxprot
- >> segment.initprot
- >> segment.nsects
- >> segment.flags;
- if (!cursor) {
- reporter_->LoadCommandTooShort(index, type);
- return false;
- }
- if (file_offset > buffer_.Size() ||
- file_size > buffer_.Size() - file_offset) {
- reporter_->MisplacedSegmentData(segment.name);
- return false;
- }
- // Mach-O files in .dSYM bundles have the contents of the loaded
- // segments removed, and their file offsets and file sizes zeroed
- // out. To help us handle this special case properly, give such
- // segments' contents NULL starting and ending pointers.
- if (file_offset == 0 && file_size == 0) {
- segment.contents.start = segment.contents.end = NULL;
- } else {
- segment.contents.start = buffer_.start + file_offset;
- segment.contents.end = segment.contents.start + file_size;
- }
- // The section list occupies the remainder of this load command's space.
- segment.section_list.start = cursor.here();
- segment.section_list.end = command.end;
-
- if (!handler->SegmentCommand(segment))
- return false;
- break;
- }
-
- case LC_SYMTAB: {
- uint32_t symoff, nsyms, stroff, strsize;
- cursor >> symoff >> nsyms >> stroff >> strsize;
- if (!cursor) {
- reporter_->LoadCommandTooShort(index, type);
- return false;
- }
- // How big are the entries in the symbol table?
- // sizeof(struct nlist_64) : sizeof(struct nlist),
- // but be paranoid about alignment vs. target architecture.
- size_t symbol_size = bits_64_ ? 16 : 12;
- // How big is the entire symbol array?
- size_t symbols_size = nsyms * symbol_size;
- if (symoff > buffer_.Size() || symbols_size > buffer_.Size() - symoff ||
- stroff > buffer_.Size() || strsize > buffer_.Size() - stroff) {
- reporter_->MisplacedSymbolTable();
- return false;
- }
- ByteBuffer entries(buffer_.start + symoff, symbols_size);
- ByteBuffer names(buffer_.start + stroff, strsize);
- if (!handler->SymtabCommand(entries, names))
- return false;
- break;
- }
-
- default: {
- if (!handler->UnknownCommand(type, command))
- return false;
- break;
- }
- }
-
- list_cursor.set_here(command.end);
- }
-
- return true;
-}
-
-// A load command handler that looks for a segment of a given name.
-class Reader::SegmentFinder : public LoadCommandHandler {
- public:
- // Create a load command handler that looks for a segment named NAME,
- // and sets SEGMENT to describe it if found.
- SegmentFinder(const string &name, Segment *segment)
- : name_(name), segment_(segment), found_() { }
-
- // Return true if the traversal found the segment, false otherwise.
- bool found() const { return found_; }
-
- bool SegmentCommand(const Segment &segment) {
- if (segment.name == name_) {
- *segment_ = segment;
- found_ = true;
- return false;
- }
- return true;
- }
-
- private:
- // The name of the segment our creator is looking for.
- const string &name_;
-
- // Where we should store the segment if found. (WEAK)
- Segment *segment_;
-
- // True if we found the segment.
- bool found_;
-};
-
-bool Reader::FindSegment(const string &name, Segment *segment) const {
- SegmentFinder finder(name, segment);
- WalkLoadCommands(&finder);
- return finder.found();
-}
-
-bool Reader::WalkSegmentSections(const Segment &segment,
- SectionHandler *handler) const {
- size_t word_size = segment.bits_64 ? 8 : 4;
- ByteCursor cursor(&segment.section_list, big_endian_);
-
- for (size_t i = 0; i < segment.nsects; i++) {
- Section section;
- section.bits_64 = segment.bits_64;
- uint64_t size;
- uint32_t offset, dummy32;
- cursor
- .CString(&section.section_name, 16)
- .CString(&section.segment_name, 16)
- .Read(word_size, false, &section.address)
- .Read(word_size, false, &size)
- >> offset
- >> section.align
- >> dummy32
- >> dummy32
- >> section.flags
- >> dummy32
- >> dummy32;
- if (section.bits_64)
- cursor >> dummy32;
- if (!cursor) {
- reporter_->SectionsMissing(segment.name);
- return false;
- }
- const uint32_t section_type = section.flags & SECTION_TYPE;
- if (section_type == S_ZEROFILL || section_type == S_THREAD_LOCAL_ZEROFILL ||
- section_type == S_GB_ZEROFILL) {
- // Zero-fill sections have a size, but no contents.
- section.contents.start = section.contents.end = NULL;
- } else if (segment.contents.start == NULL &&
- segment.contents.end == NULL) {
- // Mach-O files in .dSYM bundles have the contents of the loaded
- // segments removed, and their file offsets and file sizes zeroed
- // out. However, the sections within those segments still have
- // non-zero sizes. There's no reason to call MisplacedSectionData in
- // this case; the caller may just need the section's load
- // address. But do set the contents' limits to NULL, for safety.
- section.contents.start = section.contents.end = NULL;
- } else {
- if (offset < size_t(segment.contents.start - buffer_.start) ||
- offset > size_t(segment.contents.end - buffer_.start) ||
- size > size_t(segment.contents.end - buffer_.start - offset)) {
- reporter_->MisplacedSectionData(section.section_name,
- section.segment_name);
- return false;
- }
- section.contents.start = buffer_.start + offset;
- section.contents.end = section.contents.start + size;
- }
- if (!handler->HandleSection(section))
- return false;
- }
- return true;
-}
-
-// A SectionHandler that builds a SectionMap for the sections within a
-// given segment.
-class Reader::SectionMapper: public SectionHandler {
- public:
- // Create a SectionHandler that populates MAP with an entry for
- // each section it is given.
- SectionMapper(SectionMap *map) : map_(map) { }
- bool HandleSection(const Section &section) {
- (*map_)[section.section_name] = section;
- return true;
- }
- private:
- // The map under construction. (WEAK)
- SectionMap *map_;
-};
-
-bool Reader::MapSegmentSections(const Segment &segment,
- SectionMap *section_map) const {
- section_map->clear();
- SectionMapper mapper(section_map);
- return WalkSegmentSections(segment, &mapper);
-}
-
-} // namespace mach_o
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h
deleted file mode 100644
index 30db742db..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader.h
+++ /dev/null
@@ -1,460 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// macho_reader.h: A class for parsing Mach-O files.
-
-#ifndef BREAKPAD_COMMON_MAC_MACHO_READER_H_
-#define BREAKPAD_COMMON_MAC_MACHO_READER_H_
-
-#include <mach-o/loader.h>
-#include <mach-o/fat.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "common/byte_cursor.h"
-#include "common/mac/super_fat_arch.h"
-
-namespace google_breakpad {
-namespace mach_o {
-
-using std::map;
-using std::string;
-using std::vector;
-
-// The Mac headers don't specify particular types for these groups of
-// constants, but defining them here provides some documentation
-// value. We also give them the same width as the fields in which
-// they appear, which makes them a bit easier to use with ByteCursors.
-typedef uint32_t Magic;
-typedef uint32_t FileType;
-typedef uint32_t FileFlags;
-typedef uint32_t LoadCommandType;
-typedef uint32_t SegmentFlags;
-typedef uint32_t SectionFlags;
-
-// A parser for fat binary files, used to store universal binaries.
-// When applied to a (non-fat) Mach-O file, this behaves as if the
-// file were a fat file containing a single object file.
-class FatReader {
- public:
-
- // A class for reporting errors found while parsing fat binary files. The
- // default definitions of these methods print messages to stderr.
- class Reporter {
- public:
- // Create a reporter that attributes problems to |filename|.
- explicit Reporter(const string &filename) : filename_(filename) { }
-
- virtual ~Reporter() { }
-
- // The data does not begin with a fat binary or Mach-O magic number.
- // This is a fatal error.
- virtual void BadHeader();
-
- // The Mach-O fat binary file ends abruptly, without enough space
- // to contain an object file it claims is present.
- virtual void MisplacedObjectFile();
-
- // The file ends abruptly: either it is not large enough to hold a
- // complete header, or the header implies that contents are present
- // beyond the actual end of the file.
- virtual void TooShort();
-
- private:
- // The filename to which the reader should attribute problems.
- string filename_;
- };
-
- // Create a fat binary file reader that uses |reporter| to report problems.
- explicit FatReader(Reporter *reporter) : reporter_(reporter) { }
-
- // Read the |size| bytes at |buffer| as a fat binary file. On success,
- // return true; on failure, report the problem to reporter_ and return
- // false.
- //
- // If the data is a plain Mach-O file, rather than a fat binary file,
- // then the reader behaves as if it had found a fat binary file whose
- // single object file is the Mach-O file.
- bool Read(const uint8_t *buffer, size_t size);
-
- // Return an array of 'SuperFatArch' structures describing the
- // object files present in this fat binary file. Set |size| to the
- // number of elements in the array.
- //
- // Assuming Read returned true, the entries are validated: it is safe to
- // assume that the offsets and sizes in each SuperFatArch refer to subranges
- // of the bytes passed to Read.
- //
- // If there are no object files in this fat binary, then this
- // function can return NULL.
- //
- // The array is owned by this FatReader instance; it will be freed when
- // this FatReader is destroyed.
- //
- // This function returns a C-style array instead of a vector to make it
- // possible to use the result with OS X functions like NXFindBestFatArch,
- // so that the symbol dumper will behave consistently with other OS X
- // utilities that work with fat binaries.
- const SuperFatArch* object_files(size_t *count) const {
- *count = object_files_.size();
- if (object_files_.size() > 0)
- return &object_files_[0];
- return NULL;
- }
-
- private:
- // We use this to report problems parsing the file's contents. (WEAK)
- Reporter *reporter_;
-
- // The contents of the fat binary or Mach-O file we're parsing. We do not
- // own the storage it refers to.
- ByteBuffer buffer_;
-
- // The magic number of this binary, in host byte order.
- Magic magic_;
-
- // The list of object files in this binary.
- // object_files_.size() == fat_header.nfat_arch
- vector<SuperFatArch> object_files_;
-};
-
-// A segment in a Mach-O file. All these fields have been byte-swapped as
-// appropriate for use by the executing architecture.
-struct Segment {
- // The ByteBuffers below point into the bytes passed to the Reader that
- // created this Segment.
-
- ByteBuffer section_list; // This segment's section list.
- ByteBuffer contents; // This segment's contents.
-
- // This segment's name.
- string name;
-
- // The address at which this segment should be loaded in memory. If
- // bits_64 is false, only the bottom 32 bits of this value are valid.
- uint64_t vmaddr;
-
- // The size of this segment when loaded into memory. This may be larger
- // than contents.Size(), in which case the extra area will be
- // initialized with zeros. If bits_64 is false, only the bottom 32 bits
- // of this value are valid.
- uint64_t vmsize;
-
- // The maximum and initial VM protection of this segment's contents.
- uint32_t maxprot;
- uint32_t initprot;
-
- // The number of sections in section_list.
- uint32_t nsects;
-
- // Flags describing this segment, from SegmentFlags.
- uint32_t flags;
-
- // True if this is a 64-bit section; false if it is a 32-bit section.
- bool bits_64;
-};
-
-// A section in a Mach-O file. All these fields have been byte-swapped as
-// appropriate for use by the executing architecture.
-struct Section {
- // This section's contents. This points into the bytes passed to the
- // Reader that created this Section.
- ByteBuffer contents;
-
- // This section's name.
- string section_name; // section[_64].sectname
- // The name of the segment this section belongs to.
- string segment_name; // section[_64].segname
-
- // The address at which this section's contents should be loaded in
- // memory. If bits_64 is false, only the bottom 32 bits of this value
- // are valid.
- uint64_t address;
-
- // The contents of this section should be loaded into memory at an
- // address which is a multiple of (two raised to this power).
- uint32_t align;
-
- // Flags from SectionFlags describing the section's contents.
- uint32_t flags;
-
- // We don't support reading relocations yet.
-
- // True if this is a 64-bit section; false if it is a 32-bit section.
- bool bits_64;
-};
-
-// A map from section names to Sections.
-typedef map<string, Section> SectionMap;
-
-// A reader for a Mach-O file.
-//
-// This does not handle fat binaries; see FatReader above. FatReader
-// provides a friendly interface for parsing data that could be either a
-// fat binary or a Mach-O file.
-class Reader {
- public:
-
- // A class for reporting errors found while parsing Mach-O files. The
- // default definitions of these member functions print messages to
- // stderr.
- class Reporter {
- public:
- // Create a reporter that attributes problems to |filename|.
- explicit Reporter(const string &filename) : filename_(filename) { }
- virtual ~Reporter() { }
-
- // Reporter functions for fatal errors return void; the reader will
- // definitely return an error to its caller after calling them
-
- // The data does not begin with a Mach-O magic number, or the magic
- // number does not match the expected value for the cpu architecture.
- // This is a fatal error.
- virtual void BadHeader();
-
- // The data contained in a Mach-O fat binary (|cpu_type|, |cpu_subtype|)
- // does not match the expected CPU architecture
- // (|expected_cpu_type|, |expected_cpu_subtype|).
- virtual void CPUTypeMismatch(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype);
-
- // The file ends abruptly: either it is not large enough to hold a
- // complete header, or the header implies that contents are present
- // beyond the actual end of the file.
- virtual void HeaderTruncated();
-
- // The file's load command region, as given in the Mach-O header, is
- // too large for the file.
- virtual void LoadCommandRegionTruncated();
-
- // The file's Mach-O header claims the file contains |claimed| load
- // commands, but the I'th load command, of type |type|, extends beyond
- // the end of the load command region, as given by the Mach-O header.
- // If |type| is zero, the command's type was unreadable.
- virtual void LoadCommandsOverrun(size_t claimed, size_t i,
- LoadCommandType type);
-
- // The contents of the |i|'th load command, of type |type|, extend beyond
- // the size given in the load command's header.
- virtual void LoadCommandTooShort(size_t i, LoadCommandType type);
-
- // The LC_SEGMENT or LC_SEGMENT_64 load command for the segment named
- // |name| is too short to hold the sections that its header says it does.
- // (This more specific than LoadCommandTooShort.)
- virtual void SectionsMissing(const string &name);
-
- // The segment named |name| claims that its contents lie beyond the end
- // of the file.
- virtual void MisplacedSegmentData(const string &name);
-
- // The section named |section| in the segment named |segment| claims that
- // its contents do not lie entirely within the segment.
- virtual void MisplacedSectionData(const string &section,
- const string &segment);
-
- // The LC_SYMTAB command claims that symbol table contents are located
- // beyond the end of the file.
- virtual void MisplacedSymbolTable();
-
- // An attempt was made to read a Mach-O file of the unsupported
- // CPU architecture |cpu_type|.
- virtual void UnsupportedCPUType(cpu_type_t cpu_type);
-
- private:
- string filename_;
- };
-
- // A handler for sections parsed from a segment. The WalkSegmentSections
- // member function accepts an instance of this class, and applies it to
- // each section defined in a given segment.
- class SectionHandler {
- public:
- virtual ~SectionHandler() { }
-
- // Called to report that the segment's section list contains |section|.
- // This should return true if the iteration should continue, or false
- // if it should stop.
- virtual bool HandleSection(const Section &section) = 0;
- };
-
- // A handler for the load commands in a Mach-O file.
- class LoadCommandHandler {
- public:
- LoadCommandHandler() { }
- virtual ~LoadCommandHandler() { }
-
- // When called from WalkLoadCommands, the following handler functions
- // should return true if they wish to continue iterating over the load
- // command list, or false if they wish to stop iterating.
- //
- // When called from LoadCommandIterator::Handle or Reader::Handle,
- // these functions' return values are simply passed through to Handle's
- // caller.
- //
- // The definitions provided by this base class simply return true; the
- // default is to silently ignore sections whose member functions the
- // subclass doesn't override.
-
- // COMMAND is load command we don't recognize. We provide only the
- // command type and a ByteBuffer enclosing the command's data (If we
- // cannot parse the command type or its size, we call
- // reporter_->IncompleteLoadCommand instead.)
- virtual bool UnknownCommand(LoadCommandType type,
- const ByteBuffer &contents) {
- return true;
- }
-
- // The load command is LC_SEGMENT or LC_SEGMENT_64, defining a segment
- // with the properties given in |segment|.
- virtual bool SegmentCommand(const Segment &segment) {
- return true;
- }
-
- // The load command is LC_SYMTAB. |entries| holds the array of nlist
- // entries, and |names| holds the strings the entries refer to.
- virtual bool SymtabCommand(const ByteBuffer &entries,
- const ByteBuffer &names) {
- return true;
- }
-
- // Add handler functions for more load commands here as needed.
- };
-
- // Create a Mach-O file reader that reports problems to |reporter|.
- explicit Reader(Reporter *reporter)
- : reporter_(reporter) { }
-
- // Read the given data as a Mach-O file. The reader retains pointers
- // into the data passed, so the data should live as long as the reader
- // does. On success, return true; on failure, return false.
- //
- // At most one of these functions should be invoked once on each Reader
- // instance.
- bool Read(const uint8_t *buffer,
- size_t size,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype);
- bool Read(const ByteBuffer &buffer,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype) {
- return Read(buffer.start,
- buffer.Size(),
- expected_cpu_type,
- expected_cpu_subtype);
- }
-
- // Return this file's characteristics, as found in the Mach-O header.
- cpu_type_t cpu_type() const { return cpu_type_; }
- cpu_subtype_t cpu_subtype() const { return cpu_subtype_; }
- FileType file_type() const { return file_type_; }
- FileFlags flags() const { return flags_; }
-
- // Return true if this is a 64-bit Mach-O file, false if it is a 32-bit
- // Mach-O file.
- bool bits_64() const { return bits_64_; }
-
- // Return true if this is a big-endian Mach-O file, false if it is
- // little-endian.
- bool big_endian() const { return big_endian_; }
-
- // Apply |handler| to each load command in this Mach-O file, stopping when
- // a handler function returns false. If we encounter a malformed load
- // command, report it via reporter_ and return false. Return true if all
- // load commands were parseable and all handlers returned true.
- bool WalkLoadCommands(LoadCommandHandler *handler) const;
-
- // Set |segment| to describe the segment named |name|, if present. If
- // found, |segment|'s byte buffers refer to a subregion of the bytes
- // passed to Read. If we find the section, return true; otherwise,
- // return false.
- bool FindSegment(const string &name, Segment *segment) const;
-
- // Apply |handler| to each section defined in |segment|. If |handler| returns
- // false, stop iterating and return false. If all calls to |handler| return
- // true and we reach the end of the section list, return true.
- bool WalkSegmentSections(const Segment &segment, SectionHandler *handler)
- const;
-
- // Clear |section_map| and then populate it with a map of the sections
- // in |segment|, from section names to Section structures.
- // Each Section's contents refer to bytes in |segment|'s contents.
- // On success, return true; if a problem occurs, report it and return false.
- bool MapSegmentSections(const Segment &segment, SectionMap *section_map)
- const;
-
- private:
- // Used internally.
- class SegmentFinder;
- class SectionMapper;
-
- // We use this to report problems parsing the file's contents. (WEAK)
- Reporter *reporter_;
-
- // The contents of the Mach-O file we're parsing. We do not own the
- // storage it refers to.
- ByteBuffer buffer_;
-
- // True if this file is big-endian.
- bool big_endian_;
-
- // True if this file is a 64-bit Mach-O file.
- bool bits_64_;
-
- // This file's cpu type and subtype.
- cpu_type_t cpu_type_; // mach_header[_64].cputype
- cpu_subtype_t cpu_subtype_; // mach_header[_64].cpusubtype
-
- // This file's type.
- FileType file_type_; // mach_header[_64].filetype
-
- // The region of buffer_ occupied by load commands.
- ByteBuffer load_commands_;
-
- // The number of load commands in load_commands_.
- uint32_t load_command_count_; // mach_header[_64].ncmds
-
- // This file's header flags.
- FileFlags flags_;
-};
-
-} // namespace mach_o
-} // namespace google_breakpad
-
-#endif // BREAKPAD_COMMON_MAC_MACHO_READER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc
deleted file mode 100644
index 8ceab14bf..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_reader_unittest.cc
+++ /dev/null
@@ -1,1902 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// macho_reader_unittest.cc: Unit tests for google_breakpad::Mach_O::FatReader
-// and google_breakpad::Mach_O::Reader.
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/mac/macho_reader.h"
-#include "common/test_assembler.h"
-
-namespace mach_o = google_breakpad::mach_o;
-namespace test_assembler = google_breakpad::test_assembler;
-
-using mach_o::FatReader;
-using mach_o::FileFlags;
-using mach_o::FileType;
-using mach_o::LoadCommandType;
-using mach_o::Reader;
-using mach_o::Section;
-using mach_o::SectionMap;
-using mach_o::Segment;
-using test_assembler::Endianness;
-using test_assembler::Label;
-using test_assembler::kBigEndian;
-using test_assembler::kLittleEndian;
-using test_assembler::kUnsetEndian;
-using google_breakpad::ByteBuffer;
-using std::map;
-using std::string;
-using std::vector;
-using testing::AllOf;
-using testing::DoAll;
-using testing::Field;
-using testing::InSequence;
-using testing::Matcher;
-using testing::Return;
-using testing::SaveArg;
-using testing::Test;
-using testing::_;
-
-
-// Mock classes for the reader's various reporters and handlers.
-
-class MockFatReaderReporter: public FatReader::Reporter {
- public:
- MockFatReaderReporter(const string &filename)
- : FatReader::Reporter(filename) { }
- MOCK_METHOD0(BadHeader, void());
- MOCK_METHOD0(MisplacedObjectFile, void());
- MOCK_METHOD0(TooShort, void());
-};
-
-class MockReaderReporter: public Reader::Reporter {
- public:
- MockReaderReporter(const string &filename) : Reader::Reporter(filename) { }
- MOCK_METHOD0(BadHeader, void());
- MOCK_METHOD4(CPUTypeMismatch, void(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype));
- MOCK_METHOD0(HeaderTruncated, void());
- MOCK_METHOD0(LoadCommandRegionTruncated, void());
- MOCK_METHOD3(LoadCommandsOverrun, void(size_t claimed, size_t i,
- LoadCommandType type));
- MOCK_METHOD2(LoadCommandTooShort, void(size_t i, LoadCommandType type));
- MOCK_METHOD1(SectionsMissing, void(const string &name));
- MOCK_METHOD1(MisplacedSegmentData, void(const string &name));
- MOCK_METHOD2(MisplacedSectionData, void(const string &section,
- const string &segment));
- MOCK_METHOD0(MisplacedSymbolTable, void());
- MOCK_METHOD1(UnsupportedCPUType, void(cpu_type_t cpu_type));
-};
-
-class MockLoadCommandHandler: public Reader::LoadCommandHandler {
- public:
- MOCK_METHOD2(UnknownCommand, bool(LoadCommandType, const ByteBuffer &));
- MOCK_METHOD1(SegmentCommand, bool(const Segment &));
- MOCK_METHOD2(SymtabCommand, bool(const ByteBuffer &, const ByteBuffer &));
-};
-
-class MockSectionHandler: public Reader::SectionHandler {
- public:
- MOCK_METHOD1(HandleSection, bool(const Section &section));
-};
-
-
-// Tests for mach_o::FatReader.
-
-// Since the effect of these functions is to write to stderr, the
-// results of these tests must be inspected by hand.
-TEST(FatReaderReporter, BadHeader) {
- FatReader::Reporter reporter("filename");
- reporter.BadHeader();
-}
-
-TEST(FatReaderReporter, MisplacedObjectFile) {
- FatReader::Reporter reporter("filename");
- reporter.MisplacedObjectFile();
-}
-
-TEST(FatReaderReporter, TooShort) {
- FatReader::Reporter reporter("filename");
- reporter.TooShort();
-}
-
-TEST(MachOReaderReporter, BadHeader) {
- Reader::Reporter reporter("filename");
- reporter.BadHeader();
-}
-
-TEST(MachOReaderReporter, CPUTypeMismatch) {
- Reader::Reporter reporter("filename");
- reporter.CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL,
- CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL);
-}
-
-TEST(MachOReaderReporter, HeaderTruncated) {
- Reader::Reporter reporter("filename");
- reporter.HeaderTruncated();
-}
-
-TEST(MachOReaderReporter, LoadCommandRegionTruncated) {
- Reader::Reporter reporter("filename");
- reporter.LoadCommandRegionTruncated();
-}
-
-TEST(MachOReaderReporter, LoadCommandsOverrun) {
- Reader::Reporter reporter("filename");
- reporter.LoadCommandsOverrun(10, 9, LC_DYSYMTAB);
- reporter.LoadCommandsOverrun(10, 9, 0);
-}
-
-TEST(MachOReaderReporter, LoadCommandTooShort) {
- Reader::Reporter reporter("filename");
- reporter.LoadCommandTooShort(11, LC_SYMTAB);
-}
-
-TEST(MachOReaderReporter, SectionsMissing) {
- Reader::Reporter reporter("filename");
- reporter.SectionsMissing("segment name");
-}
-
-TEST(MachOReaderReporter, MisplacedSegmentData) {
- Reader::Reporter reporter("filename");
- reporter.MisplacedSegmentData("segment name");
-}
-
-TEST(MachOReaderReporter, MisplacedSectionData) {
- Reader::Reporter reporter("filename");
- reporter.MisplacedSectionData("section name", "segment name");
-}
-
-TEST(MachOReaderReporter, MisplacedSymbolTable) {
- Reader::Reporter reporter("filename");
- reporter.MisplacedSymbolTable();
-}
-
-TEST(MachOReaderReporter, UnsupportedCPUType) {
- Reader::Reporter reporter("filename");
- reporter.UnsupportedCPUType(CPU_TYPE_HPPA);
-}
-
-struct FatReaderFixture {
- FatReaderFixture()
- : fat(kBigEndian),
- reporter("reporter filename"),
- reader(&reporter), object_files() {
- EXPECT_CALL(reporter, BadHeader()).Times(0);
- EXPECT_CALL(reporter, TooShort()).Times(0);
-
- // here, start, and Mark are file offsets in 'fat'.
- fat.start() = 0;
- }
- // Append a 'fat_arch' entry to 'fat', with the given field values.
- void AppendFatArch(cpu_type_t type, cpu_subtype_t subtype,
- Label offset, Label size, uint32_t align) {
- fat
- .B32(type)
- .B32(subtype)
- .B32(offset)
- .B32(size)
- .B32(align);
- }
- // Append |n| dummy 'fat_arch' entries to 'fat'. The cpu type and
- // subtype have unrealistic values.
- void AppendDummyArchEntries(int n) {
- for (int i = 0; i < n; i++)
- AppendFatArch(0xb68ad617, 0x715a0840, 0, 0, 1);
- }
- void ReadFat(bool expect_parse_success = true) {
- ASSERT_TRUE(fat.GetContents(&contents));
- fat_bytes = reinterpret_cast<const uint8_t *>(contents.data());
- if (expect_parse_success) {
- EXPECT_TRUE(reader.Read(fat_bytes, contents.size()));
- size_t fat_files_count;
- const SuperFatArch* fat_files = reader.object_files(&fat_files_count);
- object_files.resize(fat_files_count);
- for (size_t i = 0; i < fat_files_count; ++i) {
- EXPECT_TRUE(fat_files[i].ConvertToFatArch(&object_files[i]));
- }
- }
- else
- EXPECT_FALSE(reader.Read(fat_bytes, contents.size()));
- }
- test_assembler::Section fat;
- MockFatReaderReporter reporter;
- FatReader reader;
- string contents;
- const uint8_t *fat_bytes;
- vector<struct fat_arch> object_files;
-};
-
-class FatReaderTest: public FatReaderFixture, public Test { };
-
-TEST_F(FatReaderTest, BadMagic) {
- EXPECT_CALL(reporter, BadHeader()).Times(1);
- fat
- .B32(0xcafed00d) // magic number (incorrect)
- .B32(10); // number of architectures
- AppendDummyArchEntries(10);
- ReadFat(false);
-}
-
-TEST_F(FatReaderTest, HeaderTooShort) {
- EXPECT_CALL(reporter, TooShort()).Times(1);
- fat
- .B32(0xcafebabe); // magic number
- ReadFat(false);
-}
-
-TEST_F(FatReaderTest, ObjectListTooShort) {
- EXPECT_CALL(reporter, TooShort()).Times(1);
- fat
- .B32(0xcafebabe) // magic number
- .B32(10); // number of architectures
- AppendDummyArchEntries(9); // nine dummy architecture entries...
- fat // and a tenth, missing a byte at the end
- .B32(0x3d46c8fc) // cpu type
- .B32(0x8a7bfb01) // cpu subtype
- .B32(0) // offset
- .B32(0) // size
- .Append(3, '*'); // one byte short of a four-byte alignment
- ReadFat(false);
-}
-
-TEST_F(FatReaderTest, DataTooShort) {
- EXPECT_CALL(reporter, MisplacedObjectFile()).Times(1);
- Label arch_data;
- fat
- .B32(0xcafebabe) // magic number
- .B32(1); // number of architectures
- AppendFatArch(0xb4d4a366, 0x4ba4f525, arch_data, 40, 0);
- fat
- .Mark(&arch_data) // file data begins here
- .Append(30, '*'); // only 30 bytes, not 40 as header claims
- ReadFat(false);
-}
-
-TEST_F(FatReaderTest, NoObjectFiles) {
- fat
- .B32(0xcafebabe) // magic number
- .B32(0); // number of architectures
- ReadFat();
- EXPECT_EQ(0U, object_files.size());
-}
-
-TEST_F(FatReaderTest, OneObjectFile) {
- Label obj1_offset;
- fat
- .B32(0xcafebabe) // magic number
- .B32(1); // number of architectures
- // First object file list entry
- AppendFatArch(0x5e3a6e91, 0x52ccd852, obj1_offset, 0x42, 0x355b15b2);
- // First object file data
- fat
- .Mark(&obj1_offset)
- .Append(0x42, '*'); // dummy contents
- ReadFat();
- ASSERT_EQ(1U, object_files.size());
- EXPECT_EQ(0x5e3a6e91, object_files[0].cputype);
- EXPECT_EQ(0x52ccd852, object_files[0].cpusubtype);
- EXPECT_EQ(obj1_offset.Value(), object_files[0].offset);
- EXPECT_EQ(0x42U, object_files[0].size);
- EXPECT_EQ(0x355b15b2U, object_files[0].align);
-}
-
-TEST_F(FatReaderTest, ThreeObjectFiles) {
- Label obj1, obj2, obj3;
- fat
- .B32(0xcafebabe) // magic number
- .B32(3); // number of architectures
- // Three object file list entries.
- AppendFatArch(0x0cb92c30, 0x6a159a71, obj1, 0xfb4, 0x2615dbe8);
- AppendFatArch(0x0f3f1cbb, 0x6c55e90f, obj2, 0xc31, 0x83af6ffd);
- AppendFatArch(0x3717276d, 0x10ecdc84, obj3, 0x4b3, 0x035267d7);
- fat
- // First object file data
- .Mark(&obj1)
- .Append(0xfb4, '*') // dummy contents
- // Second object file data
- .Mark(&obj2)
- .Append(0xc31, '%') // dummy contents
- // Third object file data
- .Mark(&obj3)
- .Append(0x4b3, '^'); // dummy contents
-
- ReadFat();
-
- ASSERT_EQ(3U, object_files.size());
-
- // First object file.
- EXPECT_EQ(0x0cb92c30, object_files[0].cputype);
- EXPECT_EQ(0x6a159a71, object_files[0].cpusubtype);
- EXPECT_EQ(obj1.Value(), object_files[0].offset);
- EXPECT_EQ(0xfb4U, object_files[0].size);
- EXPECT_EQ(0x2615dbe8U, object_files[0].align);
-
- // Second object file.
- EXPECT_EQ(0x0f3f1cbb, object_files[1].cputype);
- EXPECT_EQ(0x6c55e90f, object_files[1].cpusubtype);
- EXPECT_EQ(obj2.Value(), object_files[1].offset);
- EXPECT_EQ(0xc31U, object_files[1].size);
- EXPECT_EQ(0x83af6ffdU, object_files[1].align);
-
- // Third object file.
- EXPECT_EQ(0x3717276d, object_files[2].cputype);
- EXPECT_EQ(0x10ecdc84, object_files[2].cpusubtype);
- EXPECT_EQ(obj3.Value(), object_files[2].offset);
- EXPECT_EQ(0x4b3U, object_files[2].size);
- EXPECT_EQ(0x035267d7U, object_files[2].align);
-}
-
-TEST_F(FatReaderTest, BigEndianMachO32) {
- fat.set_endianness(kBigEndian);
- fat
- .D32(0xfeedface) // Mach-O file magic number
- .D32(0x1a9d0518) // cpu type
- .D32(0x1b779357) // cpu subtype
- .D32(0x009df67e) // file type
- .D32(0) // no load commands
- .D32(0) // the load commands occupy no bytes
- .D32(0x21987a99); // flags
-
- ReadFat();
-
- // FatReader should treat a Mach-O file as if it were a fat binary file
- // containing one object file --- the whole thing.
- ASSERT_EQ(1U, object_files.size());
- EXPECT_EQ(0x1a9d0518, object_files[0].cputype);
- EXPECT_EQ(0x1b779357, object_files[0].cpusubtype);
- EXPECT_EQ(0U, object_files[0].offset);
- EXPECT_EQ(contents.size(), object_files[0].size);
-}
-
-TEST_F(FatReaderTest, BigEndianMachO64) {
- fat.set_endianness(kBigEndian);
- fat
- .D32(0xfeedfacf) // Mach-O 64-bit file magic number
- .D32(0x5aff8487) // cpu type
- .D32(0x4c6a57f7) // cpu subtype
- .D32(0x4392d2c8) // file type
- .D32(0) // no load commands
- .D32(0) // the load commands occupy no bytes
- .D32(0x1b033eea); // flags
-
- ReadFat();
-
- // FatReader should treat a Mach-O file as if it were a fat binary file
- // containing one object file --- the whole thing.
- ASSERT_EQ(1U, object_files.size());
- EXPECT_EQ(0x5aff8487, object_files[0].cputype);
- EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype);
- EXPECT_EQ(0U, object_files[0].offset);
- EXPECT_EQ(contents.size(), object_files[0].size);
-}
-
-TEST_F(FatReaderTest, LittleEndianMachO32) {
- fat.set_endianness(kLittleEndian);
- fat
- .D32(0xfeedface) // Mach-O file magic number
- .D32(0x1a9d0518) // cpu type
- .D32(0x1b779357) // cpu subtype
- .D32(0x009df67e) // file type
- .D32(0) // no load commands
- .D32(0) // the load commands occupy no bytes
- .D32(0x21987a99); // flags
-
- ReadFat();
-
- // FatReader should treat a Mach-O file as if it were a fat binary file
- // containing one object file --- the whole thing.
- ASSERT_EQ(1U, object_files.size());
- EXPECT_EQ(0x1a9d0518, object_files[0].cputype);
- EXPECT_EQ(0x1b779357, object_files[0].cpusubtype);
- EXPECT_EQ(0U, object_files[0].offset);
- EXPECT_EQ(contents.size(), object_files[0].size);
-}
-
-TEST_F(FatReaderTest, LittleEndianMachO64) {
- fat.set_endianness(kLittleEndian);
- fat
- .D32(0xfeedfacf) // Mach-O 64-bit file magic number
- .D32(0x5aff8487) // cpu type
- .D32(0x4c6a57f7) // cpu subtype
- .D32(0x4392d2c8) // file type
- .D32(0) // no load commands
- .D32(0) // the load commands occupy no bytes
- .D32(0x1b033eea); // flags
-
- ReadFat();
-
- // FatReader should treat a Mach-O file as if it were a fat binary file
- // containing one object file --- the whole thing.
- ASSERT_EQ(1U, object_files.size());
- EXPECT_EQ(0x5aff8487, object_files[0].cputype);
- EXPECT_EQ(0x4c6a57f7, object_files[0].cpusubtype);
- EXPECT_EQ(0U, object_files[0].offset);
- EXPECT_EQ(contents.size(), object_files[0].size);
-}
-
-TEST_F(FatReaderTest, IncompleteMach) {
- fat.set_endianness(kLittleEndian);
- fat
- .D32(0xfeedfacf) // Mach-O 64-bit file magic number
- .D32(0x5aff8487); // cpu type
- // Truncated!
-
- EXPECT_CALL(reporter, TooShort()).WillOnce(Return());
-
- ReadFat(false);
-}
-
-
-// General mach_o::Reader tests.
-
-// Dynamically scoped configuration data.
-class WithConfiguration {
- public:
- // Establish the given parameters as the default for SizedSections
- // created within the dynamic scope of this instance.
- WithConfiguration(Endianness endianness, size_t word_size)
- : endianness_(endianness), word_size_(word_size), saved_(current_) {
- current_ = this;
- }
- ~WithConfiguration() { current_ = saved_; }
- static Endianness endianness() {
- assert(current_);
- return current_->endianness_;
- }
- static size_t word_size() {
- assert(current_);
- return current_->word_size_;
- }
-
- private:
- // The innermost WithConfiguration in whose dynamic scope we are
- // currently executing.
- static WithConfiguration *current_;
-
- // The innermost WithConfiguration whose dynamic scope encloses this
- // WithConfiguration.
- Endianness endianness_;
- size_t word_size_;
- WithConfiguration *saved_;
-};
-
-WithConfiguration *WithConfiguration::current_ = NULL;
-
-// A test_assembler::Section with a size that we can cite. The start(),
-// Here() and Mark() member functions of a SizedSection always represent
-// offsets within the overall file.
-class SizedSection: public test_assembler::Section {
- public:
- // Construct a section of the given endianness and word size.
- explicit SizedSection(Endianness endianness, size_t word_size)
- : test_assembler::Section(endianness), word_size_(word_size) {
- assert(word_size_ == 32 || word_size_ == 64);
- }
- SizedSection()
- : test_assembler::Section(WithConfiguration::endianness()),
- word_size_(WithConfiguration::word_size()) {
- assert(word_size_ == 32 || word_size_ == 64);
- }
-
- // Access/set this section's word size.
- size_t word_size() const { return word_size_; }
- void set_word_size(size_t word_size) {
- assert(word_size_ == 32 || word_size_ == 64);
- word_size_ = word_size;
- }
-
- // Return a label representing the size this section will have when it
- // is Placed in some containing section.
- Label final_size() const { return final_size_; }
-
- // Append SECTION to the end of this section, and call its Finish member.
- // Return a reference to this section.
- SizedSection &Place(SizedSection *section) {
- assert(section->endianness() == endianness());
- section->Finish();
- section->start() = Here();
- test_assembler::Section::Append(*section);
- return *this;
- }
-
- protected:
- // Mark this section's contents as complete. For plain SizedSections, we
- // set SECTION's start to its position in this section, and its final_size
- // label to its current size. Derived classes can extend this as needed
- // for their additional semantics.
- virtual void Finish() {
- final_size_ = Size();
- }
-
- // The word size for this data: either 32 or 64.
- size_t word_size_;
-
- private:
- // This section's final size, set when we are placed in some other
- // SizedSection.
- Label final_size_;
-};
-
-// A SizedSection that is loaded into memory at a particular address.
-class LoadedSection: public SizedSection {
- public:
- explicit LoadedSection(Label address = Label()) : address_(address) { }
-
- // Return a label representing this section's address.
- Label address() const { return address_; }
-
- // Placing a loaded section within a loaded section sets the relationship
- // between their addresses.
- LoadedSection &Place(LoadedSection *section) {
- section->address() = address() + Size();
- SizedSection::Place(section);
- return *this;
- }
-
- protected:
- // The address at which this section's contents will be loaded.
- Label address_;
-};
-
-// A SizedSection representing a segment load command.
-class SegmentLoadCommand: public SizedSection {
- public:
- SegmentLoadCommand() : section_count_(0) { }
-
- // Append a segment load command header with the given characteristics.
- // The load command will refer to CONTENTS, which must be Placed in the
- // file separately, at the desired position. Return a reference to this
- // section.
- SegmentLoadCommand &Header(const string &name, const LoadedSection &contents,
- uint32_t maxprot, uint32_t initprot,
- uint32_t flags) {
- assert(contents.word_size() == word_size());
- D32(word_size() == 32 ? LC_SEGMENT : LC_SEGMENT_64);
- D32(final_size());
- AppendCString(name, 16);
- Append(endianness(), word_size() / 8, contents.address());
- Append(endianness(), word_size() / 8, vmsize_);
- Append(endianness(), word_size() / 8, contents.start());
- Append(endianness(), word_size() / 8, contents.final_size());
- D32(maxprot);
- D32(initprot);
- D32(final_section_count_);
- D32(flags);
-
- content_final_size_ = contents.final_size();
-
- return *this;
- }
-
- // Return a label representing the size of this segment when loaded into
- // memory. If this label is still undefined by the time we place this
- // segment, it defaults to the final size of the segment's in-file
- // contents. Return a reference to this load command.
- Label &vmsize() { return vmsize_; }
-
- // Add a section entry with the given characteristics to this segment
- // load command. Return a reference to this. The section entry will refer
- // to CONTENTS, which must be Placed in the segment's contents
- // separately, at the desired position.
- SegmentLoadCommand &AppendSectionEntry(const string &section_name,
- const string &segment_name,
- uint32_t alignment, uint32_t flags,
- const LoadedSection &contents) {
- AppendCString(section_name, 16);
- AppendCString(segment_name, 16);
- Append(endianness(), word_size() / 8, contents.address());
- Append(endianness(), word_size() / 8, contents.final_size());
- D32(contents.start());
- D32(alignment);
- D32(0); // relocations start
- D32(0); // relocations size
- D32(flags);
- D32(0x93656b95); // reserved1
- D32(0xc35a2473); // reserved2
- if (word_size() == 64)
- D32(0x70284b95); // reserved3
-
- section_count_++;
-
- return *this;
- }
-
- protected:
- void Finish() {
- final_section_count_ = section_count_;
- if (!vmsize_.IsKnownConstant())
- vmsize_ = content_final_size_;
- SizedSection::Finish();
- }
-
- private:
- // The number of sections that have been added to this segment so far.
- size_t section_count_;
-
- // A label representing the final number of sections this segment will hold.
- Label final_section_count_;
-
- // The size of the contents for this segment present in the file.
- Label content_final_size_;
-
- // A label representing the size of this segment when loaded; this can be
- // larger than the size of its file contents, the difference being
- // zero-filled. If not set explicitly by calling set_vmsize, this is set
- // equal to the size of the contents.
- Label vmsize_;
-};
-
-// A SizedSection holding a list of Mach-O load commands.
-class LoadCommands: public SizedSection {
- public:
- LoadCommands() : command_count_(0) { }
-
- // Return a label representing the final load command count.
- Label final_command_count() const { return final_command_count_; }
-
- // Increment the command count; return a reference to this section.
- LoadCommands &CountCommand() {
- command_count_++;
- return *this;
- }
-
- // Place COMMAND, containing a load command, at the end of this section.
- // Return a reference to this section.
- LoadCommands &Place(SizedSection *section) {
- SizedSection::Place(section);
- CountCommand();
- return *this;
- }
-
- protected:
- // Mark this load command list as complete.
- void Finish() {
- SizedSection::Finish();
- final_command_count_ = command_count_;
- }
-
- private:
- // The number of load commands we have added to this file so far.
- size_t command_count_;
-
- // A label representing the final command count.
- Label final_command_count_;
-};
-
-// A SizedSection holding the contents of a Mach-O file. Within a
-// MachOFile, the start, Here, and Mark members refer to file offsets.
-class MachOFile: public SizedSection {
- public:
- MachOFile() {
- start() = 0;
- }
-
- // Create a Mach-O file header using the given characteristics and load
- // command list. This Places COMMANDS immediately after the header.
- // Return a reference to this section.
- MachOFile &Header(LoadCommands *commands,
- cpu_type_t cpu_type = CPU_TYPE_X86,
- cpu_subtype_t cpu_subtype = CPU_SUBTYPE_I386_ALL,
- FileType file_type = MH_EXECUTE,
- uint32_t file_flags = (MH_TWOLEVEL |
- MH_DYLDLINK |
- MH_NOUNDEFS)) {
- D32(word_size() == 32 ? 0xfeedface : 0xfeedfacf); // magic number
- D32(cpu_type); // cpu type
- D32(cpu_subtype); // cpu subtype
- D32(file_type); // file type
- D32(commands->final_command_count()); // number of load commands
- D32(commands->final_size()); // their size in bytes
- D32(file_flags); // flags
- if (word_size() == 64)
- D32(0x55638b90); // reserved
- Place(commands);
- return *this;
- }
-};
-
-
-struct ReaderFixture {
- ReaderFixture()
- : reporter("reporter filename"),
- reader(&reporter) {
- EXPECT_CALL(reporter, BadHeader()).Times(0);
- EXPECT_CALL(reporter, CPUTypeMismatch(_, _, _, _)).Times(0);
- EXPECT_CALL(reporter, HeaderTruncated()).Times(0);
- EXPECT_CALL(reporter, LoadCommandRegionTruncated()).Times(0);
- EXPECT_CALL(reporter, LoadCommandsOverrun(_, _, _)).Times(0);
- EXPECT_CALL(reporter, LoadCommandTooShort(_, _)).Times(0);
- EXPECT_CALL(reporter, SectionsMissing(_)).Times(0);
- EXPECT_CALL(reporter, MisplacedSegmentData(_)).Times(0);
- EXPECT_CALL(reporter, MisplacedSectionData(_, _)).Times(0);
- EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(0);
- EXPECT_CALL(reporter, UnsupportedCPUType(_)).Times(0);
-
- EXPECT_CALL(load_command_handler, UnknownCommand(_, _)).Times(0);
- EXPECT_CALL(load_command_handler, SegmentCommand(_)).Times(0);
- }
-
- void ReadFile(MachOFile *file,
- bool expect_parse_success,
- cpu_type_t expected_cpu_type,
- cpu_subtype_t expected_cpu_subtype) {
- ASSERT_TRUE(file->GetContents(&file_contents));
- file_bytes = reinterpret_cast<const uint8_t *>(file_contents.data());
- if (expect_parse_success) {
- EXPECT_TRUE(reader.Read(file_bytes,
- file_contents.size(),
- expected_cpu_type,
- expected_cpu_subtype));
- } else {
- EXPECT_FALSE(reader.Read(file_bytes,
- file_contents.size(),
- expected_cpu_type,
- expected_cpu_subtype));
- }
- }
-
- string file_contents;
- const uint8_t *file_bytes;
- MockReaderReporter reporter;
- Reader reader;
- MockLoadCommandHandler load_command_handler;
- MockSectionHandler section_handler;
-};
-
-class ReaderTest: public ReaderFixture, public Test { };
-
-TEST_F(ReaderTest, BadMagic) {
- WithConfiguration config(kLittleEndian, 32);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0x67bdebe1) // Not a proper magic number.
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- EXPECT_CALL(reporter, BadHeader()).WillOnce(Return());
- ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
-}
-
-TEST_F(ReaderTest, MismatchedMagic) {
- WithConfiguration config(kLittleEndian, 32);
- const cpu_type_t kCPUType = CPU_TYPE_I386;
- const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL;
- MachOFile file;
- file
- .D32(MH_CIGAM) // Right magic, but winds up wrong
- // due to bitswapping
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- EXPECT_CALL(reporter, BadHeader()).WillOnce(Return());
- ReadFile(&file, false, kCPUType, kCPUSubType);
-}
-
-TEST_F(ReaderTest, ShortMagic) {
- WithConfiguration config(kBigEndian, 32);
- MachOFile file;
- file
- .D16(0xfeed); // magic number
- // truncated!
- EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return());
- ReadFile(&file, false, CPU_TYPE_ANY, 0);
-}
-
-TEST_F(ReaderTest, ShortHeader) {
- WithConfiguration config(kBigEndian, 32);
- const cpu_type_t kCPUType = CPU_TYPE_ANY;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedface) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0); // they occupy no bytes
- EXPECT_CALL(reporter, HeaderTruncated()).WillOnce(Return());
- ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
-}
-
-TEST_F(ReaderTest, MismatchedCPU) {
- WithConfiguration config(kBigEndian, 32);
- const cpu_type_t kCPUType = CPU_TYPE_I386;
- const cpu_subtype_t kCPUSubType = CPU_SUBTYPE_X86_ALL;
- MachOFile file;
- file
- .D32(MH_MAGIC) // Right magic for PPC (once bitswapped)
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- EXPECT_CALL(reporter,
- CPUTypeMismatch(CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL,
- CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL))
- .WillOnce(Return());
- ReadFile(&file, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL);
-}
-
-TEST_F(ReaderTest, LittleEndian32Bit) {
- WithConfiguration config(kLittleEndian, 32);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedface) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
- EXPECT_FALSE(reader.bits_64());
- EXPECT_FALSE(reader.big_endian());
- EXPECT_EQ(kCPUType, reader.cpu_type());
- EXPECT_EQ(kCPUSubType, reader.cpu_subtype());
- EXPECT_EQ(FileType(0x149fc717), reader.file_type());
- EXPECT_EQ(FileFlags(0x80e71d64), reader.flags());
-}
-
-TEST_F(ReaderTest, LittleEndian64Bit) {
- WithConfiguration config(kLittleEndian, 64);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedfacf) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
- EXPECT_TRUE(reader.bits_64());
- EXPECT_FALSE(reader.big_endian());
- EXPECT_EQ(kCPUType, reader.cpu_type());
- EXPECT_EQ(kCPUSubType, reader.cpu_subtype());
- EXPECT_EQ(FileType(0x149fc717), reader.file_type());
- EXPECT_EQ(FileFlags(0x80e71d64), reader.flags());
-}
-
-TEST_F(ReaderTest, BigEndian32Bit) {
- WithConfiguration config(kBigEndian, 32);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedface) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
- EXPECT_FALSE(reader.bits_64());
- EXPECT_TRUE(reader.big_endian());
- EXPECT_EQ(kCPUType, reader.cpu_type());
- EXPECT_EQ(kCPUSubType, reader.cpu_subtype());
- EXPECT_EQ(FileType(0x149fc717), reader.file_type());
- EXPECT_EQ(FileFlags(0x80e71d64), reader.flags());
-}
-
-TEST_F(ReaderTest, BigEndian64Bit) {
- WithConfiguration config(kBigEndian, 64);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedfacf) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(0) // no load commands
- .D32(0) // they occupy no bytes
- .D32(0x80e71d64) // flags
- .D32(0); // reserved
- ReadFile(&file, true, CPU_TYPE_ANY, kCPUSubType);
- EXPECT_TRUE(reader.bits_64());
- EXPECT_TRUE(reader.big_endian());
- EXPECT_EQ(kCPUType, reader.cpu_type());
- EXPECT_EQ(kCPUSubType, reader.cpu_subtype());
- EXPECT_EQ(FileType(0x149fc717), reader.file_type());
- EXPECT_EQ(FileFlags(0x80e71d64), reader.flags());
-}
-
-
-// Load command tests.
-
-class LoadCommand: public ReaderFixture, public Test { };
-
-TEST_F(LoadCommand, RegionTruncated) {
- WithConfiguration config(kBigEndian, 64);
- const cpu_type_t kCPUType = 0x46b760df;
- const cpu_subtype_t kCPUSubType = 0x76a0e7f7;
- MachOFile file;
- file
- .D32(0xfeedfacf) // magic number
- .D32(kCPUType) // cpu type
- .D32(kCPUSubType) // cpu subtype
- .D32(0x149fc717) // file type
- .D32(1) // one load command
- .D32(40) // occupying 40 bytes
- .D32(0x80e71d64) // flags
- .D32(0) // reserved
- .Append(20, 0); // load command region, not as long as
- // Mach-O header promised
-
- EXPECT_CALL(reporter, LoadCommandRegionTruncated()).WillOnce(Return());
-
- ReadFile(&file, false, CPU_TYPE_ANY, kCPUSubType);
-}
-
-TEST_F(LoadCommand, None) {
- WithConfiguration config(kLittleEndian, 32);
- LoadCommands load_commands;
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_X86, CPU_SUBTYPE_I386_ALL);
-
- EXPECT_FALSE(reader.bits_64());
- EXPECT_FALSE(reader.big_endian());
- EXPECT_EQ(CPU_TYPE_X86, reader.cpu_type());
- EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype());
- EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type());
- EXPECT_EQ(FileFlags(MH_TWOLEVEL |
- MH_DYLDLINK |
- MH_NOUNDEFS),
- FileFlags(reader.flags()));
-
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, Unknown) {
- WithConfiguration config(kBigEndian, 32);
- LoadCommands load_commands;
- load_commands
- .CountCommand()
- .D32(0x33293d4a) // unknown load command
- .D32(40) // total size in bytes
- .Append(32, '*'); // dummy data
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_FALSE(reader.bits_64());
- EXPECT_TRUE(reader.big_endian());
- EXPECT_EQ(CPU_TYPE_X86, reader.cpu_type());
- EXPECT_EQ(CPU_SUBTYPE_I386_ALL, reader.cpu_subtype());
- EXPECT_EQ(static_cast<uint32_t>(MH_EXECUTE), reader.file_type());
- EXPECT_EQ(FileFlags(MH_TWOLEVEL |
- MH_DYLDLINK |
- MH_NOUNDEFS),
- reader.flags());
-
- ByteBuffer expected;
- expected.start = file_bytes + load_commands.start().Value();
- expected.end = expected.start + load_commands.final_size().Value();
- EXPECT_CALL(load_command_handler, UnknownCommand(0x33293d4a,
- expected))
- .WillOnce(Return(true));
-
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, TypeIncomplete) {
- WithConfiguration config(kLittleEndian, 32);
- LoadCommands load_commands;
- load_commands
- .CountCommand()
- .Append(3, 0); // load command type, incomplete
-
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, 0))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, LengthIncomplete) {
- WithConfiguration config(kBigEndian, 64);
- LoadCommands load_commands;
- load_commands
- .CountCommand()
- .D32(LC_SEGMENT); // load command
- // no length
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, ContentIncomplete) {
- WithConfiguration config(kLittleEndian, 64);
- LoadCommands load_commands;
- load_commands
- .CountCommand()
- .D32(LC_SEGMENT) // load command
- .D32(40) // total size in bytes
- .Append(28, '*'); // not enough dummy data
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, LoadCommandsOverrun(1, 0, LC_SEGMENT))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, SegmentBE32) {
- WithConfiguration config(kBigEndian, 32);
- LoadedSection segment;
- segment.address() = 0x1891139c;
- segment.Append(42, '*'); // segment contents
- SegmentLoadCommand segment_command;
- segment_command
- .Header("froon", segment, 0x94d6dd22, 0x8bdbc319, 0x990a16dd);
- segment_command.vmsize() = 0xcb76584fU;
- LoadCommands load_commands;
- load_commands.Place(&segment_command);
- MachOFile file;
- file
- .Header(&load_commands)
- .Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_CALL(load_command_handler, SegmentCommand(_))
- .WillOnce(DoAll(SaveArg<0>(&actual_segment),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(false, actual_segment.bits_64);
- EXPECT_EQ("froon", actual_segment.name);
- EXPECT_EQ(0x1891139cU, actual_segment.vmaddr);
- EXPECT_EQ(0xcb76584fU, actual_segment.vmsize);
- EXPECT_EQ(0x94d6dd22U, actual_segment.maxprot);
- EXPECT_EQ(0x8bdbc319U, actual_segment.initprot);
- EXPECT_EQ(0x990a16ddU, actual_segment.flags);
- EXPECT_EQ(0U, actual_segment.nsects);
- EXPECT_EQ(0U, actual_segment.section_list.Size());
- EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
-}
-
-TEST_F(LoadCommand, SegmentLE32) {
- WithConfiguration config(kLittleEndian, 32);
- LoadedSection segment;
- segment.address() = 0x4b877866;
- segment.Append(42, '*'); // segment contents
- SegmentLoadCommand segment_command;
- segment_command
- .Header("sixteenprecisely", segment,
- 0x350759ed, 0x6cf5a62e, 0x990a16dd);
- segment_command.vmsize() = 0xcb76584fU;
- LoadCommands load_commands;
- load_commands.Place(&segment_command);
- MachOFile file;
- file
- .Header(&load_commands)
- .Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_CALL(load_command_handler, SegmentCommand(_))
- .WillOnce(DoAll(SaveArg<0>(&actual_segment),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(false, actual_segment.bits_64);
- EXPECT_EQ("sixteenprecisely", actual_segment.name);
- EXPECT_EQ(0x4b877866U, actual_segment.vmaddr);
- EXPECT_EQ(0xcb76584fU, actual_segment.vmsize);
- EXPECT_EQ(0x350759edU, actual_segment.maxprot);
- EXPECT_EQ(0x6cf5a62eU, actual_segment.initprot);
- EXPECT_EQ(0x990a16ddU, actual_segment.flags);
- EXPECT_EQ(0U, actual_segment.nsects);
- EXPECT_EQ(0U, actual_segment.section_list.Size());
- EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
-}
-
-TEST_F(LoadCommand, SegmentBE64) {
- WithConfiguration config(kBigEndian, 64);
- LoadedSection segment;
- segment.address() = 0x79f484f77009e511ULL;
- segment.Append(42, '*'); // segment contents
- SegmentLoadCommand segment_command;
- segment_command
- .Header("froon", segment, 0x42b45da5, 0x8bdbc319, 0xb2335220);
- segment_command.vmsize() = 0x8d92397ce6248abaULL;
- LoadCommands load_commands;
- load_commands.Place(&segment_command);
- MachOFile file;
- file
- .Header(&load_commands)
- .Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_CALL(load_command_handler, SegmentCommand(_))
- .WillOnce(DoAll(SaveArg<0>(&actual_segment),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(true, actual_segment.bits_64);
- EXPECT_EQ("froon", actual_segment.name);
- EXPECT_EQ(0x79f484f77009e511ULL, actual_segment.vmaddr);
- EXPECT_EQ(0x8d92397ce6248abaULL, actual_segment.vmsize);
- EXPECT_EQ(0x42b45da5U, actual_segment.maxprot);
- EXPECT_EQ(0x8bdbc319U, actual_segment.initprot);
- EXPECT_EQ(0xb2335220U, actual_segment.flags);
- EXPECT_EQ(0U, actual_segment.nsects);
- EXPECT_EQ(0U, actual_segment.section_list.Size());
- EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
-}
-
-TEST_F(LoadCommand, SegmentLE64) {
- WithConfiguration config(kLittleEndian, 64);
- LoadedSection segment;
- segment.address() = 0x50c0501dc5922d35ULL;
- segment.Append(42, '*'); // segment contents
- SegmentLoadCommand segment_command;
- segment_command
- .Header("sixteenprecisely", segment,
- 0x917c339d, 0xdbc446fa, 0xb650b563);
- segment_command.vmsize() = 0x84ae73e7c75469bfULL;
- LoadCommands load_commands;
- load_commands.Place(&segment_command);
- MachOFile file;
- file
- .Header(&load_commands)
- .Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_CALL(load_command_handler, SegmentCommand(_))
- .WillOnce(DoAll(SaveArg<0>(&actual_segment),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(true, actual_segment.bits_64);
- EXPECT_EQ("sixteenprecisely", actual_segment.name);
- EXPECT_EQ(0x50c0501dc5922d35ULL, actual_segment.vmaddr);
- EXPECT_EQ(0x84ae73e7c75469bfULL, actual_segment.vmsize);
- EXPECT_EQ(0x917c339dU, actual_segment.maxprot);
- EXPECT_EQ(0xdbc446faU, actual_segment.initprot);
- EXPECT_EQ(0xb650b563U, actual_segment.flags);
- EXPECT_EQ(0U, actual_segment.nsects);
- EXPECT_EQ(0U, actual_segment.section_list.Size());
- EXPECT_EQ(segment.final_size().Value(), actual_segment.contents.Size());
-}
-
-TEST_F(LoadCommand, SegmentCommandTruncated) {
- WithConfiguration config(kBigEndian, 32);
- LoadedSection segment_contents;
- segment_contents.Append(20, '*'); // lah di dah
- SizedSection command;
- command
- .D32(LC_SEGMENT) // command type
- .D32(command.final_size()) // command size
- .AppendCString("too-short", 16) // segment name
- .D32(0x9c759211) // vmaddr
- .D32(segment_contents.final_size()) // vmsize
- .D32(segment_contents.start()) // file offset
- .D32(segment_contents.final_size()) // file size
- .D32(0x56f28446) // max protection
- .D32(0xe7910dcb) // initial protection
- .D32(0) // no sections
- .Append(3, 0); // flags (one byte short!)
- LoadCommands load_commands;
- load_commands.Place(&command);
- MachOFile file;
- file
- .Header(&load_commands)
- .Place(&segment_contents);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, LoadCommandTooShort(0, LC_SEGMENT))
- .WillOnce(Return());
-
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, SegmentBadContentOffset) {
- WithConfiguration config(kLittleEndian, 32);
- // Instead of letting a Place call set the segment's file offset and size,
- // set them ourselves, to check that the parser catches invalid offsets
- // instead of handing us bogus pointers.
- LoadedSection segment;
- segment.address() = 0x4db5489c;
- segment.start() = 0x7e189e76; // beyond end of file
- segment.final_size() = 0x98b9c3ab;
- SegmentLoadCommand segment_command;
- segment_command
- .Header("notmerelyfifteen", segment, 0xcbab25ee, 0x359a20db, 0x68a3933f);
- LoadCommands load_commands;
- load_commands.Place(&segment_command);
- MachOFile file;
- file.Header(&load_commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, MisplacedSegmentData("notmerelyfifteen"))
- .WillOnce(Return());
-
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(LoadCommand, ThreeLoadCommands) {
- WithConfiguration config(kBigEndian, 32);
- LoadedSection seg1, seg2, seg3;
- SegmentLoadCommand cmd1, cmd2, cmd3;
-
- seg1.Append(128, '@');
- seg1.address() = 0xa7f61ef6;
- cmd1.Header("head", seg1, 0x88bf1cc7, 0x889a26a4, 0xe9b80d87);
- // Include some dummy data at the end of the load command. Since we
- // didn't claim to have any sections, the reader should ignore this. But
- // making sure the commands have different lengths ensures that we're
- // using the right command's length to advance the LoadCommandIterator.
- cmd1.Append(128, '!');
-
- seg2.Append(42, '*');
- seg2.address() = 0xc70fc909;
- cmd2.Header("thorax", seg2, 0xde7327f4, 0xfdaf771d, 0x65e74b30);
- // More dummy data at the end of the load command.
- cmd2.Append(32, '^');
-
- seg3.Append(42, '%');
- seg3.address() = 0x46b3ab05;
- cmd3.Header("abdomen", seg3, 0x7098b70d, 0x8d8d7728, 0x5131419b);
- // More dummy data at the end of the load command.
- cmd3.Append(64, '&');
-
- LoadCommands load_commands;
- load_commands.Place(&cmd1).Place(&cmd2).Place(&cmd3);
-
- MachOFile file;
- file.Header(&load_commands).Place(&seg1).Place(&seg2).Place(&seg3);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- {
- InSequence s;
- EXPECT_CALL(load_command_handler,
- SegmentCommand(Field(&Segment::name, "head")))
- .WillOnce(Return(true));
- EXPECT_CALL(load_command_handler,
- SegmentCommand(Field(&Segment::name, "thorax")))
- .WillOnce(Return(true));
- EXPECT_CALL(load_command_handler,
- SegmentCommand(Field(&Segment::name, "abdomen")))
- .WillOnce(Return(true));
- }
-
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-static inline Matcher<const Section &> MatchSection(
- Matcher<bool> bits_64,
- Matcher<const string &> section_name,
- Matcher<const string &> segment_name,
- Matcher<uint64_t> address,
- Matcher<uint32_t> alignment,
- Matcher<uint32_t> flags,
- Matcher<const ByteBuffer &> contents) {
- return AllOf(AllOf(Field(&Section::bits_64, bits_64),
- Field(&Section::section_name, section_name),
- Field(&Section::segment_name, segment_name),
- Field(&Section::address, address)),
- AllOf(Field(&Section::align, alignment),
- Field(&Section::flags, flags),
- Field(&Section::contents, contents)));
-}
-
-static inline Matcher<const Section &> MatchSection(
- Matcher<bool> bits_64,
- Matcher<const string &> section_name,
- Matcher<const string &> segment_name,
- Matcher<uint64_t> address) {
- return AllOf(Field(&Section::bits_64, bits_64),
- Field(&Section::section_name, section_name),
- Field(&Section::segment_name, segment_name),
- Field(&Section::address, address));
-}
-
-TEST_F(LoadCommand, OneSegmentTwoSections) {
- WithConfiguration config(kBigEndian, 64);
-
- // Create some sections with some data.
- LoadedSection section1, section2;
- section1.Append("buddha's hand");
- section2.Append("kumquat");
-
- // Create a segment to hold them.
- LoadedSection segment;
- segment.address() = 0xe1d0eeec;
- segment.Place(&section2).Place(&section1);
-
- SegmentLoadCommand segment_command;
- segment_command
- .Header("head", segment, 0x92c9568c, 0xa89f2627, 0x4dc7a1e2)
- .AppendSectionEntry("mandarin", "kishu", 12, 0x8cd4604bU, section1)
- .AppendSectionEntry("bergamot", "cara cara", 12, 0x98746efaU, section2);
-
- LoadCommands commands;
- commands.Place(&segment_command);
-
- MachOFile file;
- file.Header(&commands).Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_CALL(load_command_handler, SegmentCommand(_))
- .WillOnce(DoAll(SaveArg<0>(&actual_segment),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- {
- InSequence s;
- ByteBuffer contents1;
- contents1.start = file_bytes + section1.start().Value();
- contents1.end = contents1.start + section1.final_size().Value();
- EXPECT_EQ("buddha's hand",
- string(reinterpret_cast<const char *>(contents1.start),
- contents1.Size()));
- EXPECT_CALL(section_handler,
- HandleSection(MatchSection(true, "mandarin", "kishu",
- section1.address().Value(), 12,
- 0x8cd4604bU, contents1)))
- .WillOnce(Return(true));
-
- ByteBuffer contents2;
- contents2.start = file_bytes + section2.start().Value();
- contents2.end = contents2.start + section2.final_size().Value();
- EXPECT_EQ("kumquat",
- string(reinterpret_cast<const char *>(contents2.start),
- contents2.Size()));
- EXPECT_CALL(section_handler,
- HandleSection(MatchSection(true, "bergamot", "cara cara",
- section2.address().Value(), 12,
- 0x98746efaU, contents2)))
- .WillOnce(Return(true));
- }
-
- EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, &section_handler));
-}
-
-TEST_F(LoadCommand, MisplacedSectionBefore) {
- WithConfiguration config(kLittleEndian, 64);
-
- // The segment.
- LoadedSection segment;
- segment.address() = 0x696d83cc;
- segment.Append(10, '0');
-
- // The contents of the following sections don't matter, because
- // we're not really going to Place them in segment; we're just going
- // to set all their labels by hand to get the (impossible)
- // configurations we want.
-
- // A section whose starting offset is before that of its section.
- LoadedSection before;
- before.Append(10, '1');
- before.start() = segment.start() - 1;
- before.address() = segment.address() - 1;
- before.final_size() = before.Size();
-
- SegmentLoadCommand command;
- command
- .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
- .AppendSectionEntry("before", "segment", 0, 0x686c6921, before);
-
- LoadCommands commands;
- commands.Place(&command);
-
- MachOFile file;
- file.Header(&commands).Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
-
- EXPECT_CALL(reporter, MisplacedSectionData("before", "segment"))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
-}
-
-TEST_F(LoadCommand, MisplacedSectionAfter) {
- WithConfiguration config(kLittleEndian, 64);
-
- // The segment.
- LoadedSection segment;
- segment.address() = 0x696d83cc;
- segment.Append(10, '0');
-
- // The contents of the following sections don't matter, because
- // we're not really going to Place them in segment; we're just going
- // to set all their labels by hand to get the (impossible)
- // configurations we want.
-
- // A section whose starting offset is after the end of its section.
- LoadedSection after;
- after.Append(10, '2');
- after.start() = segment.start() + 11;
- after.address() = segment.address() + 11;
- after.final_size() = after.Size();
-
- SegmentLoadCommand command;
- command
- .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
- .AppendSectionEntry("after", "segment", 0, 0x2ee50124, after);
-
- LoadCommands commands;
- commands.Place(&command);
-
- MachOFile file;
- file.Header(&commands).Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
-
- EXPECT_CALL(reporter, MisplacedSectionData("after", "segment"))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
-}
-
-TEST_F(LoadCommand, MisplacedSectionTooBig) {
- WithConfiguration config(kLittleEndian, 64);
-
- // The segment.
- LoadedSection segment;
- segment.address() = 0x696d83cc;
- segment.Append(10, '0');
-
- // The contents of the following sections don't matter, because
- // we're not really going to Place them in segment; we're just going
- // to set all their labels by hand to get the (impossible)
- // configurations we want.
-
- // A section that extends beyond the end of its section.
- LoadedSection too_big;
- too_big.Append(10, '3');
- too_big.start() = segment.start() + 1;
- too_big.address() = segment.address() + 1;
- too_big.final_size() = too_big.Size();
-
- SegmentLoadCommand command;
- command
- .Header("segment", segment, 0x173baa29, 0x8407275d, 0xed8f7057)
- .AppendSectionEntry("too big", "segment", 0, 0x8b53ae5c, too_big);
-
- LoadCommands commands;
- commands.Place(&command);
-
- MachOFile file;
- file.Header(&commands).Place(&segment);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_TRUE(reader.FindSegment("segment", &actual_segment));
-
- EXPECT_CALL(reporter, MisplacedSectionData("too big", "segment"))
- .WillOnce(Return());
- EXPECT_FALSE(reader.WalkSegmentSections(actual_segment, &section_handler));
-}
-
-
-// The segments in a .dSYM bundle's Mach-O file have their file offset
-// and size set to zero, but the sections don't. The reader shouldn't
-// report an error in this case.
-TEST_F(LoadCommand, ZappedSegment) {
- WithConfiguration config(kBigEndian, 32);
-
- // The segment.
- LoadedSection segment;
- segment.address() = 0x696d83cc;
- segment.start() = 0;
- segment.final_size() = 0;
-
- // The section.
- LoadedSection section;
- section.address() = segment.address();
- section.start() = 0;
- section.final_size() = 1000; // extends beyond its segment
-
- SegmentLoadCommand command;
- command
- .Header("zapped", segment, 0x0861a5cb, 0x68ccff67, 0x0b66255c)
- .AppendSectionEntry("twitching", "zapped", 0, 0x93b3bd42, section);
-
- LoadCommands commands;
- commands.Place(&command);
-
- MachOFile file;
- file.Header(&commands);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
- EXPECT_TRUE(reader.FindSegment("zapped", &actual_segment));
-
- ByteBuffer zapped_extent(NULL, 0);
- EXPECT_CALL(section_handler,
- HandleSection(MatchSection(false, "twitching", "zapped",
- 0x696d83cc, 0, 0x93b3bd42,
- zapped_extent)))
- .WillOnce(Return(true));
-
- EXPECT_TRUE(reader.WalkSegmentSections(actual_segment, &section_handler));
-}
-
-TEST_F(LoadCommand, MapSegmentSections) {
- WithConfiguration config(kLittleEndian, 32);
-
- // Create some sections with some data.
- LoadedSection section1, section2, section3, section4;
- section1.Append("buddha's hand");
- section2.start() = 0; // Section 2 is an S_ZEROFILL section.
- section2.final_size() = 0;
- section3.Append("shasta gold");
- section4.Append("satsuma");
-
- // Create two segments to hold them.
- LoadedSection segment1, segment2;
- segment1.address() = 0x13e6c8a9;
- segment1.Place(&section3).Place(&section1);
- segment2.set_word_size(64);
- segment2.address() = 0x04d462e2;
- segment2.Place(&section4);
- section2.address() = segment2.address() + segment2.Size();
-
- SegmentLoadCommand segment_command1, segment_command2;
- segment_command1
- .Header("head", segment1, 0x67d955a6, 0x7a61c13e, 0xe3e50c64)
- .AppendSectionEntry("mandarin", "head", 12, 0x5bb565d7, section1)
- .AppendSectionEntry("bergamot", "head", 12, 0x8620de73, section3);
- segment_command2.set_word_size(64);
- segment_command2
- .Header("thorax", segment2, 0x7aab2419, 0xe908007f, 0x17961d33)
- .AppendSectionEntry("sixteenprecisely", "thorax",
- 12, S_ZEROFILL, section2)
- .AppendSectionEntry("cara cara", "thorax", 12, 0xb6c5dd8a, section4);
-
- LoadCommands commands;
- commands.Place(&segment_command1).Place(&segment_command2);
-
- MachOFile file;
- file.Header(&commands).Place(&segment1).Place(&segment2);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment segment;
- SectionMap section_map;
-
- EXPECT_FALSE(reader.FindSegment("smoot", &segment));
-
- ASSERT_TRUE(reader.FindSegment("thorax", &segment));
- ASSERT_TRUE(reader.MapSegmentSections(segment, &section_map));
-
- EXPECT_FALSE(section_map.find("sixteenpreciselyandthensome")
- != section_map.end());
- EXPECT_FALSE(section_map.find("mandarin") != section_map.end());
- ASSERT_TRUE(section_map.find("cara cara") != section_map.end());
- EXPECT_THAT(section_map["cara cara"],
- MatchSection(true, "cara cara", "thorax", 0x04d462e2));
- ASSERT_TRUE(section_map.find("sixteenprecisely")
- != section_map.end());
- ByteBuffer sixteenprecisely_contents(NULL, 0);
- EXPECT_THAT(section_map["sixteenprecisely"],
- MatchSection(true, "sixteenprecisely", "thorax",
- 0x04d462e2 + 7, 12, S_ZEROFILL,
- sixteenprecisely_contents));
-
- ASSERT_TRUE(reader.FindSegment("head", &segment));
- ASSERT_TRUE(reader.MapSegmentSections(segment, &section_map));
-
- ASSERT_TRUE(section_map.find("mandarin") != section_map.end());
- EXPECT_THAT(section_map["mandarin"],
- MatchSection(false, "mandarin", "head", 0x13e6c8a9 + 11));
- ASSERT_TRUE(section_map.find("bergamot") != section_map.end());
- EXPECT_THAT(section_map["bergamot"],
- MatchSection(false, "bergamot", "head", 0x13e6c8a9));
-}
-
-TEST_F(LoadCommand, FindSegment) {
- WithConfiguration config(kBigEndian, 32);
-
- LoadedSection segment1, segment2, segment3;
- segment1.address() = 0xb8ae5752;
- segment1.Append("Some contents!");
- segment2.address() = 0xd6b0ce83;
- segment2.Append("Different stuff.");
- segment3.address() = 0x7374fd2a;
- segment3.Append("Further materials.");
-
- SegmentLoadCommand cmd1, cmd2, cmd3;
- cmd1.Header("first", segment1, 0xfadb6932, 0x175bf529, 0x0de790ad);
- cmd2.Header("second", segment2, 0xeef716e0, 0xe103a9d7, 0x7d38a8ef);
- cmd3.Header("third", segment3, 0xe172b39e, 0x86012f07, 0x080ac94d);
-
- LoadCommands commands;
- commands.Place(&cmd1).Place(&cmd2).Place(&cmd3);
-
- MachOFile file;
- file.Header(&commands).Place(&segment1).Place(&segment2).Place(&segment3);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- Segment actual_segment;
-
- EXPECT_FALSE(reader.FindSegment("murphy", &actual_segment));
-
- EXPECT_TRUE(reader.FindSegment("second", &actual_segment));
- EXPECT_EQ(0xd6b0ce83, actual_segment.vmaddr);
-}
-
-
-// Symtab tests.
-
-// A StringAssembler is a class for generating .stabstr sections to present
-// as input to the STABS parser.
-class StringAssembler: public SizedSection {
- public:
- // Add the string S to this StringAssembler, and return the string's
- // offset within this compilation unit's strings.
- size_t Add(const string &s) {
- size_t offset = Size();
- AppendCString(s);
- return offset;
- }
-};
-
-// A SymbolAssembler is a class for generating .stab sections to present as
-// test input for the STABS parser.
-class SymbolAssembler: public SizedSection {
- public:
- // Create a SymbolAssembler that uses StringAssembler for its strings.
- explicit SymbolAssembler(StringAssembler *string_assembler)
- : string_assembler_(string_assembler),
- entry_count_(0) { }
-
- // Append a STAB entry to the end of this section with the given
- // characteristics. NAME is the offset of this entry's name string within
- // its compilation unit's portion of the .stabstr section; this can be a
- // value generated by a StringAssembler. Return a reference to this
- // SymbolAssembler.
- SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor,
- Label value, Label name) {
- D32(name);
- D8(type);
- D8(other);
- D16(descriptor);
- Append(endianness(), word_size_ / 8, value);
- entry_count_++;
- return *this;
- }
-
- // As above, but automatically add NAME to our StringAssembler.
- SymbolAssembler &Symbol(uint8_t type, uint8_t other, Label descriptor,
- Label value, const string &name) {
- return Symbol(type, other, descriptor, value, string_assembler_->Add(name));
- }
-
- private:
- // The strings for our STABS entries.
- StringAssembler *string_assembler_;
-
- // The number of entries in this compilation unit so far.
- size_t entry_count_;
-};
-
-class Symtab: public ReaderFixture, public Test { };
-
-TEST_F(Symtab, Symtab32) {
- WithConfiguration config(kLittleEndian, 32);
-
- StringAssembler strings;
- SymbolAssembler symbols(&strings);
- symbols
- .Symbol(0x52, 0x7c, 0x3470, 0x9bb02e7c, "hrududu")
- .Symbol(0x50, 0x90, 0x7520, 0x1122525d, "Frith");
-
- SizedSection symtab_command;
- symtab_command
- .D32(LC_SYMTAB) // command
- .D32(symtab_command.final_size()) // size
- .D32(symbols.start()) // file offset of symbols
- .D32(2) // symbol count
- .D32(strings.start()) // file offset of strings
- .D32(strings.final_size()); // strings size
-
- LoadCommands load_commands;
- load_commands.Place(&symtab_command);
-
- MachOFile file;
- file.Header(&load_commands).Place(&symbols).Place(&strings);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- ByteBuffer symbols_found, strings_found;
- EXPECT_CALL(load_command_handler, SymtabCommand(_, _))
- .WillOnce(DoAll(SaveArg<0>(&symbols_found),
- SaveArg<1>(&strings_found),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(24U, symbols_found.Size());
- EXPECT_EQ(14U, strings_found.Size());
-}
-
-TEST_F(Symtab, Symtab64) {
- WithConfiguration config(kBigEndian, 64);
-
- StringAssembler strings;
- SymbolAssembler symbols(&strings);
- symbols
- .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
- .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
-
- SizedSection symtab_command;
- symtab_command
- .D32(LC_SYMTAB) // command
- .D32(symtab_command.final_size()) // size
- .D32(symbols.start()) // file offset of symbols
- .D32(2) // symbol count
- .D32(strings.start()) // file offset of strings
- .D32(strings.final_size()); // strings size
-
- LoadCommands load_commands;
- load_commands.Place(&symtab_command);
-
- MachOFile file;
- file.Header(&load_commands).Place(&symbols).Place(&strings);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- ByteBuffer symbols_found, strings_found;
- EXPECT_CALL(load_command_handler, SymtabCommand(_, _))
- .WillOnce(DoAll(SaveArg<0>(&symbols_found),
- SaveArg<1>(&strings_found),
- Return(true)));
- EXPECT_TRUE(reader.WalkLoadCommands(&load_command_handler));
-
- EXPECT_EQ(32U, symbols_found.Size());
- EXPECT_EQ(8U, strings_found.Size());
-}
-
-TEST_F(Symtab, SymtabMisplacedSymbols) {
- WithConfiguration config(kBigEndian, 32);
-
- StringAssembler strings;
- SymbolAssembler symbols(&strings);
- symbols
- .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
- .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
-
- SizedSection symtab_command;
- symtab_command
- .D32(LC_SYMTAB) // command
- .D32(symtab_command.final_size()) // size
- .D32(symbols.start()) // file offset of symbols
- .D32(3) // symbol count (too many)
- .D32(strings.start()) // file offset of strings
- .D32(strings.final_size()); // strings size
-
- LoadCommands load_commands;
- load_commands.Place(&symtab_command);
-
- MachOFile file;
- // Put symbols at end, so the excessive length will be noticed.
- file.Header(&load_commands).Place(&strings).Place(&symbols);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1);
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
-TEST_F(Symtab, SymtabMisplacedStrings) {
- WithConfiguration config(kLittleEndian, 32);
-
- StringAssembler strings;
- SymbolAssembler symbols(&strings);
- symbols
- .Symbol(0xa7, 0xaf, 0x03af, 0x42f3072c74335181ULL, "foo")
- .Symbol(0xb0, 0x9a, 0x2aa7, 0x2e2d349b3d5744a0ULL, "bar");
-
- SizedSection symtab_command;
- symtab_command
- .D32(LC_SYMTAB) // command
- .D32(symtab_command.final_size()) // size
- .D32(symbols.start()) // file offset of symbols
- .D32(2) // symbol count
- .D32(strings.start()) // file offset of strings
- .D32(strings.final_size() + 1); // strings size (too long)
-
- LoadCommands load_commands;
- load_commands.Place(&symtab_command);
-
- MachOFile file;
- // Put strings at end, so the excessive length will be noticed.
- file.Header(&load_commands).Place(&symbols).Place(&strings);
-
- ReadFile(&file, true, CPU_TYPE_ANY, 0);
-
- EXPECT_CALL(reporter, MisplacedSymbolTable()).Times(1);
- EXPECT_FALSE(reader.WalkLoadCommands(&load_command_handler));
-}
-
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc
deleted file mode 100644
index f56fe768c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_utilties.cc: Utilities for dealing with mach-o files
-//
-// Author: Dave Camp
-
-#include "common/mac/byteswap.h"
-#include "common/mac/macho_utilities.h"
-
-#include <mach-o/fat.h>
-#include <mach-o/loader.h>
-
-void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc) {
- uc->cmd = ByteSwap(uc->cmd);
- uc->cmdsize = ByteSwap(uc->cmdsize);
-}
-
-void breakpad_swap_load_command(struct load_command *lc) {
- lc->cmd = ByteSwap(lc->cmd);
- lc->cmdsize = ByteSwap(lc->cmdsize);
-}
-
-void breakpad_swap_dylib_command(struct dylib_command *dc) {
- dc->cmd = ByteSwap(dc->cmd);
- dc->cmdsize = ByteSwap(dc->cmdsize);
-
- dc->dylib.name.offset = ByteSwap(dc->dylib.name.offset);
- dc->dylib.timestamp = ByteSwap(dc->dylib.timestamp);
- dc->dylib.current_version = ByteSwap(dc->dylib.current_version);
- dc->dylib.compatibility_version = ByteSwap(dc->dylib.compatibility_version);
-}
-
-void breakpad_swap_segment_command(struct segment_command *sc) {
- sc->cmd = ByteSwap(sc->cmd);
- sc->cmdsize = ByteSwap(sc->cmdsize);
-
- sc->vmaddr = ByteSwap(sc->vmaddr);
- sc->vmsize = ByteSwap(sc->vmsize);
- sc->fileoff = ByteSwap(sc->fileoff);
- sc->filesize = ByteSwap(sc->filesize);
- sc->maxprot = ByteSwap(sc->maxprot);
- sc->initprot = ByteSwap(sc->initprot);
- sc->nsects = ByteSwap(sc->nsects);
- sc->flags = ByteSwap(sc->flags);
-}
-
-void breakpad_swap_segment_command_64(struct segment_command_64 *sg) {
- sg->cmd = ByteSwap(sg->cmd);
- sg->cmdsize = ByteSwap(sg->cmdsize);
-
- sg->vmaddr = ByteSwap(sg->vmaddr);
- sg->vmsize = ByteSwap(sg->vmsize);
- sg->fileoff = ByteSwap(sg->fileoff);
- sg->filesize = ByteSwap(sg->filesize);
-
- sg->maxprot = ByteSwap(sg->maxprot);
- sg->initprot = ByteSwap(sg->initprot);
- sg->nsects = ByteSwap(sg->nsects);
- sg->flags = ByteSwap(sg->flags);
-}
-
-void breakpad_swap_fat_header(struct fat_header *fh) {
- fh->magic = ByteSwap(fh->magic);
- fh->nfat_arch = ByteSwap(fh->nfat_arch);
-}
-
-void breakpad_swap_fat_arch(struct fat_arch *fa, uint32_t narchs) {
- for (uint32_t i = 0; i < narchs; ++i) {
- fa[i].cputype = ByteSwap(fa[i].cputype);
- fa[i].cpusubtype = ByteSwap(fa[i].cpusubtype);
- fa[i].offset = ByteSwap(fa[i].offset);
- fa[i].size = ByteSwap(fa[i].size);
- fa[i].align = ByteSwap(fa[i].align);
- }
-}
-
-void breakpad_swap_mach_header(struct mach_header *mh) {
- mh->magic = ByteSwap(mh->magic);
- mh->cputype = ByteSwap(mh->cputype);
- mh->cpusubtype = ByteSwap(mh->cpusubtype);
- mh->filetype = ByteSwap(mh->filetype);
- mh->ncmds = ByteSwap(mh->ncmds);
- mh->sizeofcmds = ByteSwap(mh->sizeofcmds);
- mh->flags = ByteSwap(mh->flags);
-}
-
-void breakpad_swap_mach_header_64(struct mach_header_64 *mh) {
- mh->magic = ByteSwap(mh->magic);
- mh->cputype = ByteSwap(mh->cputype);
- mh->cpusubtype = ByteSwap(mh->cpusubtype);
- mh->filetype = ByteSwap(mh->filetype);
- mh->ncmds = ByteSwap(mh->ncmds);
- mh->sizeofcmds = ByteSwap(mh->sizeofcmds);
- mh->flags = ByteSwap(mh->flags);
- mh->reserved = ByteSwap(mh->reserved);
-}
-
-void breakpad_swap_section(struct section *s,
- uint32_t nsects) {
- for (uint32_t i = 0; i < nsects; i++) {
- s[i].addr = ByteSwap(s[i].addr);
- s[i].size = ByteSwap(s[i].size);
-
- s[i].offset = ByteSwap(s[i].offset);
- s[i].align = ByteSwap(s[i].align);
- s[i].reloff = ByteSwap(s[i].reloff);
- s[i].nreloc = ByteSwap(s[i].nreloc);
- s[i].flags = ByteSwap(s[i].flags);
- s[i].reserved1 = ByteSwap(s[i].reserved1);
- s[i].reserved2 = ByteSwap(s[i].reserved2);
- }
-}
-
-void breakpad_swap_section_64(struct section_64 *s,
- uint32_t nsects) {
- for (uint32_t i = 0; i < nsects; i++) {
- s[i].addr = ByteSwap(s[i].addr);
- s[i].size = ByteSwap(s[i].size);
-
- s[i].offset = ByteSwap(s[i].offset);
- s[i].align = ByteSwap(s[i].align);
- s[i].reloff = ByteSwap(s[i].reloff);
- s[i].nreloc = ByteSwap(s[i].nreloc);
- s[i].flags = ByteSwap(s[i].flags);
- s[i].reserved1 = ByteSwap(s[i].reserved1);
- s[i].reserved2 = ByteSwap(s[i].reserved2);
- }
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h
deleted file mode 100644
index 00563a77c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_utilities.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_utilities.h: Utilities for dealing with mach-o files
-//
-// Author: Dave Camp
-
-#ifndef COMMON_MAC_MACHO_UTILITIES_H__
-#define COMMON_MAC_MACHO_UTILITIES_H__
-
-#include <mach-o/loader.h>
-#include <mach/thread_status.h>
-
-/* Some #defines and structs that aren't defined in older SDKs */
-#ifndef CPU_ARCH_ABI64
-# define CPU_ARCH_ABI64 0x01000000
-#endif
-
-#ifndef CPU_TYPE_X86
-# define CPU_TYPE_X86 CPU_TYPE_I386
-#endif
-
-#ifndef CPU_TYPE_POWERPC64
-# define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
-#endif
-
-#ifndef LC_UUID
-# define LC_UUID 0x1b /* the uuid */
-#endif
-
-// The uuid_command struct/swap routines were added during the 10.4 series.
-// Their presence isn't guaranteed.
-struct breakpad_uuid_command {
- uint32_t cmd; /* LC_UUID */
- uint32_t cmdsize; /* sizeof(struct uuid_command) */
- uint8_t uuid[16]; /* the 128-bit uuid */
-};
-
-void breakpad_swap_uuid_command(struct breakpad_uuid_command *uc);
-
-void breakpad_swap_load_command(struct load_command *lc);
-
-void breakpad_swap_dylib_command(struct dylib_command *dc);
-
-// Older SDKs defines thread_state_data_t as an int[] instead
-// of the natural_t[] it should be.
-typedef natural_t breakpad_thread_state_data_t[THREAD_STATE_MAX];
-
-void breakpad_swap_segment_command(struct segment_command *sc);
-
-// The 64-bit swap routines were added during the 10.4 series, their
-// presence isn't guaranteed.
-void breakpad_swap_segment_command_64(struct segment_command_64 *sg);
-
-void breakpad_swap_fat_header(struct fat_header *fh);
-
-void breakpad_swap_fat_arch(struct fat_arch *fa, uint32_t narchs);
-
-void breakpad_swap_mach_header(struct mach_header *mh);
-
-void breakpad_swap_mach_header_64(struct mach_header_64 *mh);
-
-void breakpad_swap_section(struct section *s,
- uint32_t nsects);
-
-void breakpad_swap_section_64(struct section_64 *s,
- uint32_t nsects);
-
-#endif
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc
deleted file mode 100644
index 1acd86656..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.cc
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_walker.cc: Iterate over the load commands in a mach-o file
-//
-// See macho_walker.h for documentation
-//
-// Author: Dan Waylonis
-
-#include <assert.h>
-#include <fcntl.h>
-#include <mach-o/arch.h>
-#include <mach-o/fat.h>
-#include <mach-o/loader.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "common/mac/byteswap.h"
-#include "common/mac/macho_walker.h"
-#include "common/mac/macho_utilities.h"
-
-namespace MacFileUtilities {
-
-MachoWalker::MachoWalker(const char *path, LoadCommandCallback callback,
- void *context)
- : file_(-1),
- memory_(NULL),
- memory_size_(0),
- callback_(callback),
- callback_context_(context),
- current_header_(NULL),
- current_header_size_(0),
- current_header_offset_(0) {
- file_ = open(path, O_RDONLY);
-}
-
-MachoWalker::MachoWalker(void *memory, size_t size,
- LoadCommandCallback callback, void *context)
- : file_(-1),
- memory_(memory),
- memory_size_(size),
- callback_(callback),
- callback_context_(context),
- current_header_(NULL),
- current_header_size_(0),
- current_header_offset_(0) {
-}
-
-MachoWalker::~MachoWalker() {
- if (file_ != -1)
- close(file_);
-}
-
-bool MachoWalker::WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
- cpu_type_t valid_cpu_type = cpu_type;
- cpu_subtype_t valid_cpu_subtype = cpu_subtype;
- // if |cpu_type| is 0, use the native cpu type.
- if (cpu_type == 0) {
- const NXArchInfo *arch = NXGetLocalArchInfo();
- assert(arch);
- valid_cpu_type = arch->cputype;
- valid_cpu_subtype = CPU_SUBTYPE_MULTIPLE;
- }
- off_t offset;
- if (FindHeader(valid_cpu_type, valid_cpu_subtype, offset)) {
- if (cpu_type & CPU_ARCH_ABI64)
- return WalkHeader64AtOffset(offset);
-
- return WalkHeaderAtOffset(offset);
- }
-
- return false;
-}
-
-bool MachoWalker::ReadBytes(void *buffer, size_t size, off_t offset) {
- if (memory_) {
- if (offset < 0)
- return false;
- bool result = true;
- if (offset + size > memory_size_) {
- if (static_cast<size_t>(offset) >= memory_size_)
- return false;
- size = memory_size_ - static_cast<size_t>(offset);
- result = false;
- }
- memcpy(buffer, static_cast<char *>(memory_) + offset, size);
- return result;
- } else {
- return pread(file_, buffer, size, offset) == (ssize_t)size;
- }
-}
-
-bool MachoWalker::CurrentHeader(struct mach_header_64 *header, off_t *offset) {
- if (current_header_) {
- memcpy(header, current_header_, sizeof(mach_header_64));
- *offset = current_header_offset_;
- return true;
- }
-
- return false;
-}
-
-bool MachoWalker::FindHeader(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- off_t &offset) {
- // Read the magic bytes that's common amongst all mach-o files
- uint32_t magic;
- if (!ReadBytes(&magic, sizeof(magic), 0))
- return false;
-
- offset = sizeof(magic);
-
- // Figure out what type of file we've got
- bool is_fat = false;
- if (magic == FAT_MAGIC || magic == FAT_CIGAM) {
- is_fat = true;
- }
- else if (magic != MH_MAGIC && magic != MH_CIGAM && magic != MH_MAGIC_64 &&
- magic != MH_CIGAM_64) {
- return false;
- }
-
- if (!is_fat) {
- // If we don't have a fat header, check if the cpu type matches the single
- // header
- struct mach_header header;
- if (!ReadBytes(&header, sizeof(header), 0))
- return false;
-
- if (magic == MH_CIGAM || magic == MH_CIGAM_64)
- breakpad_swap_mach_header(&header);
-
- if (cpu_type != header.cputype ||
- (cpu_subtype != CPU_SUBTYPE_MULTIPLE &&
- cpu_subtype != header.cpusubtype)) {
- return false;
- }
-
- offset = 0;
- return true;
- } else {
- // Read the fat header and find an appropriate architecture
- offset = 0;
- struct fat_header fat;
- if (!ReadBytes(&fat, sizeof(fat), offset))
- return false;
-
- if (NXHostByteOrder() != NX_BigEndian)
- breakpad_swap_fat_header(&fat);
-
- offset += sizeof(fat);
-
- // Search each architecture for the desired one
- struct fat_arch arch;
- for (uint32_t i = 0; i < fat.nfat_arch; ++i) {
- if (!ReadBytes(&arch, sizeof(arch), offset))
- return false;
-
- if (NXHostByteOrder() != NX_BigEndian)
- breakpad_swap_fat_arch(&arch, 1);
-
- if (arch.cputype == cpu_type &&
- (cpu_subtype == CPU_SUBTYPE_MULTIPLE ||
- arch.cpusubtype == cpu_subtype)) {
- offset = arch.offset;
- return true;
- }
-
- offset += sizeof(arch);
- }
- }
-
- return false;
-}
-
-bool MachoWalker::WalkHeaderAtOffset(off_t offset) {
- struct mach_header header;
- if (!ReadBytes(&header, sizeof(header), offset))
- return false;
-
- bool swap = (header.magic == MH_CIGAM);
- if (swap)
- breakpad_swap_mach_header(&header);
-
- // Copy the data into the mach_header_64 structure. Since the 32-bit and
- // 64-bit only differ in the last field (reserved), this is safe to do.
- struct mach_header_64 header64;
- memcpy((void *)&header64, (const void *)&header, sizeof(header));
- header64.reserved = 0;
-
- current_header_ = &header64;
- current_header_size_ = sizeof(header); // 32-bit, not 64-bit
- current_header_offset_ = offset;
- offset += current_header_size_;
- bool result = WalkHeaderCore(offset, header.ncmds, swap);
- current_header_ = NULL;
- current_header_size_ = 0;
- current_header_offset_ = 0;
- return result;
-}
-
-bool MachoWalker::WalkHeader64AtOffset(off_t offset) {
- struct mach_header_64 header;
- if (!ReadBytes(&header, sizeof(header), offset))
- return false;
-
- bool swap = (header.magic == MH_CIGAM_64);
- if (swap)
- breakpad_swap_mach_header_64(&header);
-
- current_header_ = &header;
- current_header_size_ = sizeof(header);
- current_header_offset_ = offset;
- offset += current_header_size_;
- bool result = WalkHeaderCore(offset, header.ncmds, swap);
- current_header_ = NULL;
- current_header_size_ = 0;
- current_header_offset_ = 0;
- return result;
-}
-
-bool MachoWalker::WalkHeaderCore(off_t offset, uint32_t number_of_commands,
- bool swap) {
- for (uint32_t i = 0; i < number_of_commands; ++i) {
- struct load_command cmd;
- if (!ReadBytes(&cmd, sizeof(cmd), offset))
- return false;
-
- if (swap)
- breakpad_swap_load_command(&cmd);
-
- // Call the user callback
- if (callback_ && !callback_(this, &cmd, offset, swap, callback_context_))
- break;
-
- offset += cmd.cmdsize;
- }
-
- return true;
-}
-
-} // namespace MacFileUtilities
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h b/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h
deleted file mode 100644
index dd535814a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/macho_walker.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// macho_walker.h: Iterate over the load commands in a mach-o file
-//
-// Author: Dan Waylonis
-
-#ifndef COMMON_MAC_MACHO_WALKER_H__
-#define COMMON_MAC_MACHO_WALKER_H__
-
-#include <mach/machine.h>
-#include <mach-o/loader.h>
-#include <sys/types.h>
-
-namespace MacFileUtilities {
-
-class MachoWalker {
- public:
- // A callback function executed when a new load command is read. If no
- // further processing of load commands is desired, return false. Otherwise,
- // return true.
- // |cmd| is the current command, and |offset| is the location relative to the
- // beginning of the file (not header) where the command was read. If |swap|
- // is set, then any command data (other than the returned load_command) should
- // be swapped when read
- typedef bool (*LoadCommandCallback)(MachoWalker *walker, load_command *cmd,
- off_t offset, bool swap, void *context);
-
- MachoWalker(const char *path, LoadCommandCallback callback, void *context);
- MachoWalker(void *memory, size_t size, LoadCommandCallback callback,
- void *context);
- ~MachoWalker();
-
- // Begin walking the header for |cpu_type| and |cpu_subtype|. If |cpu_type|
- // is 0, then the native cpu type is used. Otherwise, accepted values are
- // listed in /usr/include/mach/machine.h (e.g., CPU_TYPE_X86 or
- // CPU_TYPE_POWERPC). If |cpu_subtype| is CPU_SUBTYPE_MULTIPLE, the match is
- // only done on |cpu_type|.
- // Returns false if opening the file failed or if the |cpu_type|/|cpu_subtype|
- // is not present in the file.
- bool WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
-
- // Read |size| bytes from the opened file at |offset| into |buffer|
- bool ReadBytes(void *buffer, size_t size, off_t offset);
-
- // Return the current header and header offset
- bool CurrentHeader(struct mach_header_64 *header, off_t *offset);
-
- private:
- // Locate (if any) the header offset for |cpu_type| and return in |offset|.
- // Return true if found, false otherwise.
- bool FindHeader(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype,
- off_t &offset);
-
- // Process an individual header starting at |offset| from the start of the
- // file. Return true if successful, false otherwise.
- bool WalkHeaderAtOffset(off_t offset);
- bool WalkHeader64AtOffset(off_t offset);
-
- // Bottleneck for walking the load commands
- bool WalkHeaderCore(off_t offset, uint32_t number_of_commands, bool swap);
-
- // File descriptor to the opened file
- int file_;
-
- // Memory location to read from.
- void *memory_;
-
- // Size of the memory segment we can read from.
- size_t memory_size_;
-
- // User specified callback & context
- LoadCommandCallback callback_;
- void *callback_context_;
-
- // Current header, size, and offset. The mach_header_64 is used for both
- // 32-bit and 64-bit headers because they only differ in their last field
- // (reserved). By adding the |current_header_size_| and the
- // |current_header_offset_|, you can determine the offset in the file just
- // after the header.
- struct mach_header_64 *current_header_;
- unsigned long current_header_size_;
- off_t current_header_offset_;
-
- private:
- MachoWalker(const MachoWalker &);
- MachoWalker &operator=(const MachoWalker &);
-};
-
-} // namespace MacFileUtilities
-
-#endif // COMMON_MAC_MACHO_WALKER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build b/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build
deleted file mode 100644
index 6d6df28e2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/moz.build
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-UNIFIED_SOURCES += [
- 'arch_utilities.cc',
- 'file_id.cc',
- 'macho_id.cc',
- 'macho_reader.cc',
- 'macho_utilities.cc',
- 'macho_walker.cc',
-]
-
-if CONFIG['HOST_OS_ARCH'] != 'Darwin':
- HOST_CXXFLAGS += [
- '-I%s/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/' % TOPSRCDIR,
- ]
-
-# This is a little weird, but we're building a host and a target lib here.
-# The host lib is used for dump_syms, and the target lib for the
-# crash reporter client. Therefore, we don't need all the srcs in both.
-if CONFIG['MOZ_CRASHREPORTER']:
- HOST_SOURCES += UNIFIED_SOURCES
- HOST_SOURCES += [
- 'dump_syms.cc',
- ]
- HOST_CXXFLAGS += [
- '-O2',
- '-g',
- '-stdlib=libc++',
- ]
- HostLibrary('host_breakpad_mac_common_s')
-
-SOURCES += [
- 'bootstrap_compat.cc',
- 'HTTPMultipartUpload.m',
- 'MachIPC.mm',
- 'string_utilities.cc',
-]
-
-Library('breakpad_mac_common_s')
-
-# We allow warnings for third-party code that can be updated from upstream.
-ALLOW_COMPILER_WARNINGS = True
-
-FINAL_LIBRARY = 'xul'
-
-CMFLAGS += ['-std=c99']
-
-include('/toolkit/crashreporter/crashreporter.mozbuild')
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h b/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h
deleted file mode 100644
index d6d1bef97..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/scoped_task_suspend-inl.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-// Inline implementation of ScopedTaskSuspend, which suspends a Mach
-// task for the duration of its scope.
-
-#ifndef GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_
-#define GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_
-
-#include <mach/mach.h>
-
-namespace google_breakpad {
-
-class ScopedTaskSuspend {
- public:
- explicit ScopedTaskSuspend(mach_port_t target) : target_(target) {
- task_suspend(target_);
- }
-
- ~ScopedTaskSuspend() {
- task_resume(target_);
- }
-
- private:
- mach_port_t target_;
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_COMMON_MAC_SCOPED_TASK_SUSPEND_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc
deleted file mode 100644
index 07c0f4268..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/scoped_ptr.h"
-#include "common/mac/string_utilities.h"
-
-namespace MacStringUtils {
-
-using google_breakpad::scoped_array;
-
-std::string ConvertToString(CFStringRef str) {
- CFIndex length = CFStringGetLength(str);
- std::string result;
-
- if (!length)
- return result;
-
- CFIndex maxUTF8Length =
- CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8);
- scoped_array<UInt8> buffer(new UInt8[maxUTF8Length + 1]);
- CFIndex actualUTF8Length;
- CFStringGetBytes(str, CFRangeMake(0, length), kCFStringEncodingUTF8, 0,
- false, buffer.get(), maxUTF8Length, &actualUTF8Length);
- buffer[actualUTF8Length] = 0;
- result.assign((const char *)buffer.get());
-
- return result;
-}
-
-unsigned int IntegerValueAtIndex(string &str, unsigned int idx) {
- string digits("0123456789"), temp;
- size_t start = 0;
- size_t end;
- size_t found = 0;
- unsigned int result = 0;
-
- for (; found <= idx; ++found) {
- end = str.find_first_not_of(digits, start);
-
- if (end == string::npos)
- end = str.size();
-
- temp = str.substr(start, end - start);
-
- if (found == idx) {
- result = atoi(temp.c_str());
- }
-
- start = str.find_first_of(digits, end + 1);
-
- if (start == string::npos)
- break;
- }
-
- return result;
-}
-
-} // namespace MacStringUtils
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h b/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h
deleted file mode 100644
index 6d89c834e..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/string_utilities.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// string_utilities.h: Utilities for strings for Mac platform
-
-#ifndef COMMON_MAC_STRING_UTILITIES_H__
-#define COMMON_MAC_STRING_UTILITIES_H__
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include <string>
-
-namespace MacStringUtils {
-
-using std::string;
-
-// Convert a CoreFoundation string into a std::string
-string ConvertToString(CFStringRef str);
-
-// Return the idx'th decimal integer in str, separated by non-decimal-digits
-// E.g., str = 10.4.8, idx = 1 -> 4
-unsigned int IntegerValueAtIndex(string &str, unsigned int idx);
-
-} // namespace MacStringUtils
-
-#endif // COMMON_MAC_STRING_UTILITIES_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h b/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h
deleted file mode 100644
index 501c8652a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/super_fat_arch.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2015, 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.
-
-// Original author: Erik Chen <erikchen@chromium.org>
-
-// super_fat_arch.h: A class to handle 64-bit object files. Has conversions to
-// and from struct fat_arch.
-
-#ifndef BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_
-#define BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_
-
-#include <limits>
-#include <mach-o/fat.h>
-#include <stdint.h>
-
-// Similar to struct fat_arch, except size-related parameters support
-// 64-bits.
-class SuperFatArch {
- public:
- uint32_t cputype;
- uint32_t cpusubtype;
- uint64_t offset;
- uint64_t size;
- uint64_t align;
-
- SuperFatArch() :
- cputype(0),
- cpusubtype(0),
- offset(0),
- size(0),
- align(0) {
- }
-
- explicit SuperFatArch(const struct fat_arch &arch) :
- cputype(arch.cputype),
- cpusubtype(arch.cpusubtype),
- offset(arch.offset),
- size(arch.size),
- align(arch.align) {
- }
-
- // Returns false if the conversion cannot be made.
- // If the conversion succeeds, the result is placed in |output_arch|.
- bool ConvertToFatArch(struct fat_arch* output_arch) const {
- if (offset > std::numeric_limits<uint32_t>::max())
- return false;
- if (size > std::numeric_limits<uint32_t>::max())
- return false;
- if (align > std::numeric_limits<uint32_t>::max())
- return false;
- struct fat_arch arch;
- arch.cputype = cputype;
- arch.cpusubtype = cpusubtype;
- arch.offset = offset;
- arch.size = size;
- arch.align = align;
- *output_arch = arch;
- return true;
- }
-};
-
-#endif // BREAKPAD_COMMON_MAC_SUPER_FAT_ARCH_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h
deleted file mode 100644
index ce3d9022c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.h
+++ /dev/null
@@ -1,1110 +0,0 @@
-//
-// GTMSenTestCase.h
-//
-// Copyright 2007-2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-// Portions of this file fall under the following license, marked with
-// SENTE_BEGIN - SENTE_END
-//
-// Copyright (c) 1997-2005, Sen:te (Sente SA). All rights reserved.
-//
-// Use of this source code is governed by the following license:
-//
-// 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.
-//
-// 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 Sente SA 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.
-//
-// Note: this license is equivalent to the FreeBSD license.
-//
-// This notice may not be removed from this file.
-
-// Some extra test case macros that would have been convenient for SenTestingKit
-// to provide. I didn't stick GTM in front of the Macro names, so that they would
-// be easy to remember.
-
-#import "GTMDefines.h"
-
-#if (!GTM_IPHONE_SDK) || (GTM_IPHONE_USE_SENTEST)
-#import <SenTestingKit/SenTestingKit.h>
-#else
-#import <Foundation/Foundation.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined __clang__
-// gcc and gcc-llvm do not allow you to use STAssert(blah, nil) with nil
-// as a description if you have the NS_FORMAT_FUNCTION on.
-// clang however will not compile without warnings if you don't have it.
-NSString *STComposeString(NSString *, ...) NS_FORMAT_FUNCTION(1, 2);
-#else
-NSString *STComposeString(NSString *, ...);
-#endif // __clang__
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // !GTM_IPHONE_SDK || GTM_IPHONE_USE_SENTEST
-
-// Generates a failure when a1 != noErr
-// Args:
-// a1: should be either an OSErr or an OSStatus
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNoErr(a1, description, ...) \
-do { \
- @try { \
- OSStatus a1value = (a1); \
- if (a1value != noErr) { \
- NSString *_expression = [NSString stringWithFormat:@"Expected noErr, got %ld for (%s)", (long)a1value, #a1]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == noErr fails", #a1] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when a1 != a2
-// Args:
-// a1: received value. Should be either an OSErr or an OSStatus
-// a2: expected value. Should be either an OSErr or an OSStatus
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertErr(a1, a2, description, ...) \
-do { \
- @try { \
- OSStatus a1value = (a1); \
- OSStatus a2value = (a2); \
- if (a1value != a2value) { \
- NSString *_expression = [NSString stringWithFormat:@"Expected %s(%ld) but got %ld for (%s)", #a2, (long)a2value, (long)a1value, #a1]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s) fails", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-
-// Generates a failure when a1 is NULL
-// Args:
-// a1: should be a pointer (use STAssertNotNil for an object)
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNotNULL(a1, description, ...) \
-do { \
- @try { \
- __typeof__(a1) a1value = (a1); \
- if (a1value == (__typeof__(a1))NULL) { \
- NSString *_expression = [NSString stringWithFormat:@"((%s) != NULL)", #a1]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != NULL fails", #a1] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when a1 is not NULL
-// Args:
-// a1: should be a pointer (use STAssertNil for an object)
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNULL(a1, description, ...) \
-do { \
- @try { \
- __typeof__(a1) a1value = (a1); \
- if (a1value != (__typeof__(a1))NULL) { \
- NSString *_expression = [NSString stringWithFormat:@"((%s) == NULL)", #a1]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == NULL fails", #a1] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when a1 is equal to a2. This test is for C scalars,
-// structs and unions.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNotEquals(a1, a2, description, ...) \
-do { \
- @try { \
- if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
- } else { \
- __typeof__(a1) a1value = (a1); \
- __typeof__(a2) a2value = (a2); \
- NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
- NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
- if ([a1encoded isEqualToValue:a2encoded]) { \
- NSString *_expression = [NSString stringWithFormat:@"((%s) != (%s))", #a1, #a2]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- }\
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when a1 is equal to a2. This test is for objects.
-// Args:
-// a1: argument 1. object.
-// a2: argument 2. object.
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNotEqualObjects(a1, a2, description, ...) \
-do { \
- @try {\
- id a1value = (a1); \
- id a2value = (a2); \
- if ( (strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \
- (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \
- (![(id)a1value isEqual:(id)a2value]) ) continue; \
- [self failWithException:([NSException failureInEqualityBetweenObject:a1value \
- andObject:a2value \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- }\
- @catch (id anException) {\
- [self failWithException:([NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- }\
-} while(0)
-
-// Generates a failure when a1 is not 'op' to a2. This test is for C scalars.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// op: operation
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertOperation(a1, a2, op, description, ...) \
-do { \
- @try { \
- if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
- } else { \
- __typeof__(a1) a1value = (a1); \
- __typeof__(a2) a2value = (a2); \
- if (!(a1value op a2value)) { \
- double a1DoubleValue = a1value; \
- double a2DoubleValue = a2value; \
- NSString *_expression = [NSString stringWithFormat:@"(%s (%lg) %s %s (%lg))", #a1, a1DoubleValue, #op, #a2, a2DoubleValue]; \
- [self failWithException:([NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)])]; \
- } \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException \
- failureInRaise:[NSString stringWithFormat:@"(%s) %s (%s)", #a1, #op, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when a1 is not > a2. This test is for C scalars.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// op: operation
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertGreaterThan(a1, a2, description, ...) \
- STAssertOperation(a1, a2, >, description, ##__VA_ARGS__)
-
-// Generates a failure when a1 is not >= a2. This test is for C scalars.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// op: operation
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertGreaterThanOrEqual(a1, a2, description, ...) \
- STAssertOperation(a1, a2, >=, description, ##__VA_ARGS__)
-
-// Generates a failure when a1 is not < a2. This test is for C scalars.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// op: operation
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertLessThan(a1, a2, description, ...) \
- STAssertOperation(a1, a2, <, description, ##__VA_ARGS__)
-
-// Generates a failure when a1 is not <= a2. This test is for C scalars.
-// Args:
-// a1: argument 1
-// a2: argument 2
-// op: operation
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertLessThanOrEqual(a1, a2, description, ...) \
- STAssertOperation(a1, a2, <=, description, ##__VA_ARGS__)
-
-// Generates a failure when string a1 is not equal to string a2. This call
-// differs from STAssertEqualObjects in that strings that are different in
-// composition (precomposed vs decomposed) will compare equal if their final
-// representation is equal.
-// ex O + umlaut decomposed is the same as O + umlaut composed.
-// Args:
-// a1: string 1
-// a2: string 2
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertEqualStrings(a1, a2, description, ...) \
-do { \
- @try { \
- id a1value = (a1); \
- id a2value = (a2); \
- if (a1value == a2value) continue; \
- if ([a1value isKindOfClass:[NSString class]] && \
- [a2value isKindOfClass:[NSString class]] && \
- [a1value compare:a2value options:0] == NSOrderedSame) continue; \
- [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
- andObject:a2value \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when string a1 is equal to string a2. This call
-// differs from STAssertEqualObjects in that strings that are different in
-// composition (precomposed vs decomposed) will compare equal if their final
-// representation is equal.
-// ex O + umlaut decomposed is the same as O + umlaut composed.
-// Args:
-// a1: string 1
-// a2: string 2
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNotEqualStrings(a1, a2, description, ...) \
-do { \
- @try { \
- id a1value = (a1); \
- id a2value = (a2); \
- if ([a1value isKindOfClass:[NSString class]] && \
- [a2value isKindOfClass:[NSString class]] && \
- [a1value compare:a2value options:0] != NSOrderedSame) continue; \
- [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
- andObject:a2value \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when c-string a1 is not equal to c-string a2.
-// Args:
-// a1: string 1
-// a2: string 2
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertEqualCStrings(a1, a2, description, ...) \
-do { \
- @try { \
- const char* a1value = (a1); \
- const char* a2value = (a2); \
- if (a1value == a2value) continue; \
- if (strcmp(a1value, a2value) == 0) continue; \
- [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \
- andObject:[NSString stringWithUTF8String:a2value] \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-// Generates a failure when c-string a1 is equal to c-string a2.
-// Args:
-// a1: string 1
-// a2: string 2
-// description: A format string as in the printf() function. Can be nil or
-// an empty string but must be present.
-// ...: A variable number of arguments to the format string. Can be absent.
-#define STAssertNotEqualCStrings(a1, a2, description, ...) \
-do { \
- @try { \
- const char* a1value = (a1); \
- const char* a2value = (a2); \
- if (strcmp(a1value, a2value) != 0) continue; \
- [self failWithException:[NSException failureInEqualityBetweenObject:[NSString stringWithUTF8String:a1value] \
- andObject:[NSString stringWithUTF8String:a2value] \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false.
- This test is for GLKit types (GLKVector, GLKMatrix) where small differences
- could make these items not exactly equal. Do not use this version directly.
- Use the explicit STAssertEqualGLKVectors and STAssertEqualGLKMatrices defined
- below.
- _{a1 The GLKType on the left.}
- _{a2 The GLKType on the right.}
- _{accuracy The maximum difference between a1 and a2 for these values to be
- considered equal.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-
-#define STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ...) \
-do { \
- @try { \
- if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
- } else { \
- __typeof__(a1) a1GLKValue = (a1); \
- __typeof__(a2) a2GLKValue = (a2); \
- __typeof__(accuracy) accuracyvalue = (accuracy); \
- float *a1FloatValue = ((float*)&a1GLKValue); \
- float *a2FloatValue = ((float*)&a2GLKValue); \
- for (size_t i = 0; i < sizeof(__typeof__(a1)) / sizeof(float); ++i) { \
- float a1value = a1FloatValue[i]; \
- float a2value = a2FloatValue[i]; \
- if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \
- NSMutableArray *strings = [NSMutableArray arrayWithCapacity:sizeof(a1) / sizeof(float)]; \
- NSString *string; \
- for (size_t j = 0; j < sizeof(__typeof__(a1)) / sizeof(float); ++j) { \
- string = [NSString stringWithFormat:@"(%0.3f == %0.3f)", a1FloatValue[j], a2FloatValue[j]]; \
- [strings addObject:string]; \
- } \
- string = [strings componentsJoinedByString:@", "]; \
- NSString *desc = STComposeString(description, ##__VA_ARGS__); \
- desc = [NSString stringWithFormat:@"%@ With Accuracy %0.3f: %@", string, (float)accuracyvalue, desc]; \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", desc]]; \
- break; \
- } \
- } \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-#define STAssertEqualGLKVectors(a1, a2, accuracy, description, ...) \
- STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
-
-#define STAssertEqualGLKMatrices(a1, a2, accuracy, description, ...) \
- STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
-
-#define STAssertEqualGLKQuaternions(a1, a2, accuracy, description, ...) \
- STInternalAssertEqualGLKVectorsOrMatrices(a1, a2, accuracy, description, ##__VA_ARGS__)
-
-#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
-// When not using the Xcode provided version, define everything ourselves.
-
-// SENTE_BEGIN
-/*" Generates a failure when !{ [a1 isEqualTo:a2] } is false
- (or one is nil and the other is not).
- _{a1 The object on the left.}
- _{a2 The object on the right.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertEqualObjects(a1, a2, description, ...) \
-do { \
- @try { \
- id a1value = (a1); \
- id a2value = (a2); \
- if (a1value == a2value) continue; \
- if ((strcmp(@encode(__typeof__(a1value)), @encode(id)) == 0) && \
- (strcmp(@encode(__typeof__(a2value)), @encode(id)) == 0) && \
- [(id)a1value isEqual:(id)a2value]) continue; \
- [self failWithException:[NSException failureInEqualityBetweenObject:a1value \
- andObject:a2value \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-
-/*" Generates a failure when a1 is not equal to a2. This test is for
- C scalars, structs and unions.
- _{a1 The argument on the left.}
- _{a2 The argument on the right.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertEquals(a1, a2, description, ...) \
-do { \
- @try { \
- if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
- } else { \
- __typeof__(a1) a1value = (a1); \
- __typeof__(a2) a2value = (a2); \
- NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
- NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
- if (![a1encoded isEqualToValue:a2encoded]) { \
- [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \
- andValue:a2encoded \
- withAccuracy:nil \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-#define STAbsoluteDifference(left,right) (MAX(left,right)-MIN(left,right))
-
-
-/*" Generates a failure when a1 is not equal to a2 within + or - accuracy is false.
- This test is for scalars such as floats and doubles where small differences
- could make these items not exactly equal, but also works for all scalars.
- _{a1 The scalar on the left.}
- _{a2 The scalar on the right.}
- _{accuracy The maximum difference between a1 and a2 for these values to be
- considered equal.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-
-#define STAssertEqualsWithAccuracy(a1, a2, accuracy, description, ...) \
-do { \
- @try { \
- if (strcmp(@encode(__typeof__(a1)), @encode(__typeof__(a2)))) { \
- [self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"Type mismatch -- %@", STComposeString(description, ##__VA_ARGS__)]]; \
- } else { \
- __typeof__(a1) a1value = (a1); \
- __typeof__(a2) a2value = (a2); \
- __typeof__(accuracy) accuracyvalue = (accuracy); \
- if (STAbsoluteDifference(a1value, a2value) > accuracyvalue) { \
- NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \
- NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \
- NSValue *accuracyencoded = [NSValue value:&accuracyvalue withObjCType:@encode(__typeof__(accuracy))]; \
- [self failWithException:[NSException failureInEqualityBetweenValue:a1encoded \
- andValue:a2encoded \
- withAccuracy:accuracyencoded \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == (%s)", #a1, #a2] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-
-
-/*" Generates a failure unconditionally.
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STFail(description, ...) \
-[self failWithException:[NSException failureInFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]
-
-
-
-/*" Generates a failure when a1 is not nil.
- _{a1 An object.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertNil(a1, description, ...) \
-do { \
- @try { \
- id a1value = (a1); \
- if (a1value != nil) { \
- NSString *_a1 = [NSString stringWithUTF8String:#a1]; \
- NSString *_expression = [NSString stringWithFormat:@"((%@) == nil)", _a1]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) == nil fails", #a1] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-
-/*" Generates a failure when a1 is nil.
- _{a1 An object.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertNotNil(a1, description, ...) \
-do { \
- @try { \
- id a1value = (a1); \
- if (a1value == nil) { \
- NSString *_a1 = [NSString stringWithUTF8String:#a1]; \
- NSString *_expression = [NSString stringWithFormat:@"((%@) != nil)", _a1]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) != nil fails", #a1] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while(0)
-
-
-/*" Generates a failure when expression evaluates to false.
- _{expr The expression that is tested.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertTrue(expr, description, ...) \
-do { \
- BOOL _evaluatedExpression = (expr); \
- if (!_evaluatedExpression) { \
- NSString *_expression = [NSString stringWithUTF8String:#expr]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while (0)
-
-
-/*" Generates a failure when expression evaluates to false and in addition will
- generate error messages if an exception is encountered.
- _{expr The expression that is tested.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertTrueNoThrow(expr, description, ...) \
-do { \
- @try { \
- BOOL _evaluatedExpression = (expr); \
- if (!_evaluatedExpression) { \
- NSString *_expression = [NSString stringWithUTF8String:#expr]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:NO \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"(%s) ", #expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while (0)
-
-
-/*" Generates a failure when the expression evaluates to true.
- _{expr The expression that is tested.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertFalse(expr, description, ...) \
-do { \
- BOOL _evaluatedExpression = (expr); \
- if (_evaluatedExpression) { \
- NSString *_expression = [NSString stringWithUTF8String:#expr]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:YES \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while (0)
-
-
-/*" Generates a failure when the expression evaluates to true and in addition
- will generate error messages if an exception is encountered.
- _{expr The expression that is tested.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertFalseNoThrow(expr, description, ...) \
-do { \
- @try { \
- BOOL _evaluatedExpression = (expr); \
- if (_evaluatedExpression) { \
- NSString *_expression = [NSString stringWithUTF8String:#expr]; \
- [self failWithException:[NSException failureInCondition:_expression \
- isTrue:YES \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithFormat:@"!(%s) ", #expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while (0)
-
-
-/*" Generates a failure when expression does not throw an exception.
- _{expression The expression that is evaluated.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.
-"*/
-#define STAssertThrows(expr, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (id anException) { \
- continue; \
- } \
- [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:nil \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
-} while (0)
-
-
-/*" Generates a failure when expression does not throw an exception of a
- specific class.
- _{expression The expression that is evaluated.}
- _{specificException The specified class of the exception.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertThrowsSpecific(expr, specificException, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (specificException *anException) { \
- continue; \
- } \
- @catch (id anException) { \
- NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
- [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
- continue; \
- } \
- NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
- [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:nil \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
-} while (0)
-
-
-/*" Generates a failure when expression does not throw an exception of a
- specific class with a specific name. Useful for those frameworks like
- AppKit or Foundation that throw generic NSException w/specific names
- (NSInvalidArgumentException, etc).
- _{expression The expression that is evaluated.}
- _{specificException The specified class of the exception.}
- _{aName The name of the specified exception.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-
-"*/
-#define STAssertThrowsSpecificNamed(expr, specificException, aName, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (specificException *anException) { \
- if ([aName isEqualToString:[anException name]]) continue; \
- NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \
- [self failWithException: \
- [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
- continue; \
- } \
- @catch (id anException) { \
- NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
- [self failWithException: \
- [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
- continue; \
- } \
- NSString *_descrip = STComposeString(@"(Expected exception: %@) %@", NSStringFromClass([specificException class]), description); \
- [self failWithException: \
- [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:nil \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
-} while (0)
-
-
-/*" Generates a failure when expression does throw an exception.
- _{expression The expression that is evaluated.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertNoThrow(expr, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (id anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
-} while (0)
-
-
-/*" Generates a failure when expression does throw an exception of the specitied
- class. Any other exception is okay (i.e. does not generate a failure).
- _{expression The expression that is evaluated.}
- _{specificException The specified class of the exception.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-"*/
-#define STAssertNoThrowSpecific(expr, specificException, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (specificException *anException) { \
- [self failWithException:[NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(description, ##__VA_ARGS__)]]; \
- } \
- @catch (id anythingElse) { \
- ; \
- } \
-} while (0)
-
-
-/*" Generates a failure when expression does throw an exception of a
- specific class with a specific name. Useful for those frameworks like
- AppKit or Foundation that throw generic NSException w/specific names
- (NSInvalidArgumentException, etc).
- _{expression The expression that is evaluated.}
- _{specificException The specified class of the exception.}
- _{aName The name of the specified exception.}
- _{description A format string as in the printf() function. Can be nil or
- an empty string but must be present.}
- _{... A variable number of arguments to the format string. Can be absent.}
-
-"*/
-#define STAssertNoThrowSpecificNamed(expr, specificException, aName, description, ...) \
-do { \
- @try { \
- (expr); \
- } \
- @catch (specificException *anException) { \
- if ([aName isEqualToString:[anException name]]) { \
- NSString *_descrip = STComposeString(@"(Expected exception: %@ (name: %@)) %@", NSStringFromClass([specificException class]), aName, description); \
- [self failWithException: \
- [NSException failureInRaise:[NSString stringWithUTF8String:#expr] \
- exception:anException \
- inFile:[NSString stringWithUTF8String:__FILE__] \
- atLine:__LINE__ \
- withDescription:@"%@", STComposeString(_descrip, ##__VA_ARGS__)]]; \
- } \
- continue; \
- } \
- @catch (id anythingElse) { \
- ; \
- } \
-} while (0)
-
-
-
-@interface NSException (GTMSenTestAdditions)
-+ (NSException *)failureInFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(3, 4);
-+ (NSException *)failureInCondition:(NSString *)condition
- isTrue:(BOOL)isTrue
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
-+ (NSException *)failureInEqualityBetweenObject:(id)left
- andObject:(id)right
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
-+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
- andValue:(NSValue *)right
- withAccuracy:(NSValue *)accuracy
- inFile:(NSString *)filename
- atLine:(int) ineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(6, 7);
-+ (NSException *)failureInRaise:(NSString *)expression
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(4, 5);
-+ (NSException *)failureInRaise:(NSString *)expression
- exception:(NSException *)exception
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... NS_FORMAT_FUNCTION(5, 6);
-@end
-
-// SENTE_END
-
-@protocol SenTestCase
-+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation;
-- (id)initWithInvocation:(NSInvocation *)anInvocation;
-- (void)setUp;
-- (void)invokeTest;
-- (void)tearDown;
-- (void)performTest;
-- (void)failWithException:(NSException*)exception;
-- (NSInvocation *)invocation;
-- (SEL)selector;
-+ (NSArray *)testInvocations;
-@end
-
-@interface SenTestCase : NSObject<SenTestCase> {
- @private
- NSInvocation *invocation_;
-}
-@end
-
-GTM_EXTERN NSString *const SenTestFailureException;
-
-GTM_EXTERN NSString *const SenTestFilenameKey;
-GTM_EXTERN NSString *const SenTestLineNumberKey;
-
-#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
-
-// All unittest cases in GTM should inherit from GTMTestCase. It makes sure
-// to set up our logging system correctly to verify logging calls.
-// See GTMUnitTestDevLog.h for details
-@interface GTMTestCase : SenTestCase
-
-// Returns YES if this is an abstract testCase class as opposed to a concrete
-// testCase class that you want tests run against. SenTestCase is not designed
-// out of the box to handle an abstract class hierarchy descending from it with
-// some concrete subclasses. In some cases we want all the "concrete"
-// subclasses of an abstract subclass of SenTestCase to run a test, but we don't
-// want that test to be run against an instance of an abstract subclass itself.
-// By returning "YES" here, the tests defined by this class won't be run against
-// an instance of this class. As an example class hierarchy:
-//
-// FooExtensionTestCase
-// GTMTestCase <- ExtensionAbstractTestCase <
-// BarExtensionTestCase
-//
-// So FooExtensionTestCase and BarExtensionTestCase inherit from
-// ExtensionAbstractTestCase (and probably FooExtension and BarExtension inherit
-// from a class named Extension). We want the tests in ExtensionAbstractTestCase
-// to be run as part of FooExtensionTestCase and BarExtensionTestCase, but we
-// don't want them run against ExtensionAbstractTestCase. The default
-// implementation checks to see if the name of the class contains the word
-// "AbstractTest" (case sensitive).
-+ (BOOL)isAbstractTestCase;
-
-@end
diff --git a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m b/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m
deleted file mode 100644
index 162f01e97..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/mac/testing/GTMSenTestCase.m
+++ /dev/null
@@ -1,428 +0,0 @@
-//
-// GTMSenTestCase.m
-//
-// Copyright 2007-2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-#import "GTMSenTestCase.h"
-
-#import <unistd.h>
-#if GTM_IPHONE_SIMULATOR
-#import <objc/message.h>
-#endif
-
-#import "GTMObjC2Runtime.h"
-#import "GTMUnitTestDevLog.h"
-
-#if GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
-#import <stdarg.h>
-
-@interface NSException (GTMSenTestPrivateAdditions)
-+ (NSException *)failureInFile:(NSString *)filename
- atLine:(int)lineNumber
- reason:(NSString *)reason;
-@end
-
-@implementation NSException (GTMSenTestPrivateAdditions)
-+ (NSException *)failureInFile:(NSString *)filename
- atLine:(int)lineNumber
- reason:(NSString *)reason {
- NSDictionary *userInfo =
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInteger:lineNumber], SenTestLineNumberKey,
- filename, SenTestFilenameKey,
- nil];
-
- return [self exceptionWithName:SenTestFailureException
- reason:reason
- userInfo:userInfo];
-}
-@end
-
-@implementation NSException (GTMSenTestAdditions)
-
-+ (NSException *)failureInFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason = testDescription;
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-+ (NSException *)failureInCondition:(NSString *)condition
- isTrue:(BOOL)isTrue
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason = [NSString stringWithFormat:@"'%@' should be %s. %@",
- condition, isTrue ? "false" : "true", testDescription];
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-+ (NSException *)failureInEqualityBetweenObject:(id)left
- andObject:(id)right
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason =
- [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
- [left description], [right description], testDescription];
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-+ (NSException *)failureInEqualityBetweenValue:(NSValue *)left
- andValue:(NSValue *)right
- withAccuracy:(NSValue *)accuracy
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason;
- if (accuracy) {
- reason =
- [NSString stringWithFormat:@"'%@' should be equal to '%@'. %@",
- left, right, testDescription];
- } else {
- reason =
- [NSString stringWithFormat:@"'%@' should be equal to '%@' +/-'%@'. %@",
- left, right, accuracy, testDescription];
- }
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-+ (NSException *)failureInRaise:(NSString *)expression
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason = [NSString stringWithFormat:@"'%@' should raise. %@",
- expression, testDescription];
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-+ (NSException *)failureInRaise:(NSString *)expression
- exception:(NSException *)exception
- inFile:(NSString *)filename
- atLine:(int)lineNumber
- withDescription:(NSString *)formatString, ... {
-
- NSString *testDescription = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- testDescription =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
-
- NSString *reason;
- if ([[exception name] isEqualToString:SenTestFailureException]) {
- // it's our exception, assume it has the right description on it.
- reason = [exception reason];
- } else {
- // not one of our exception, use the exceptions reason and our description
- reason = [NSString stringWithFormat:@"'%@' raised '%@'. %@",
- expression, [exception reason], testDescription];
- }
-
- return [self failureInFile:filename atLine:lineNumber reason:reason];
-}
-
-@end
-
-NSString *STComposeString(NSString *formatString, ...) {
- NSString *reason = @"";
- if (formatString) {
- va_list vl;
- va_start(vl, formatString);
- reason =
- [[[NSString alloc] initWithFormat:formatString arguments:vl] autorelease];
- va_end(vl);
- }
- return reason;
-}
-
-NSString *const SenTestFailureException = @"SenTestFailureException";
-NSString *const SenTestFilenameKey = @"SenTestFilenameKey";
-NSString *const SenTestLineNumberKey = @"SenTestLineNumberKey";
-
-@interface SenTestCase (SenTestCasePrivate)
-// our method of logging errors
-+ (void)printException:(NSException *)exception fromTestName:(NSString *)name;
-@end
-
-@implementation SenTestCase
-+ (id)testCaseWithInvocation:(NSInvocation *)anInvocation {
- return [[[self alloc] initWithInvocation:anInvocation] autorelease];
-}
-
-- (id)initWithInvocation:(NSInvocation *)anInvocation {
- if ((self = [super init])) {
- invocation_ = [anInvocation retain];
- }
- return self;
-}
-
-- (void)dealloc {
- [invocation_ release];
- [super dealloc];
-}
-
-- (void)failWithException:(NSException*)exception {
- [exception raise];
-}
-
-- (void)setUp {
-}
-
-- (void)performTest {
- @try {
- [self invokeTest];
- } @catch (NSException *exception) {
- [[self class] printException:exception
- fromTestName:NSStringFromSelector([self selector])];
- [exception raise];
- }
-}
-
-- (NSInvocation *)invocation {
- return invocation_;
-}
-
-- (SEL)selector {
- return [invocation_ selector];
-}
-
-+ (void)printException:(NSException *)exception fromTestName:(NSString *)name {
- NSDictionary *userInfo = [exception userInfo];
- NSString *filename = [userInfo objectForKey:SenTestFilenameKey];
- NSNumber *lineNumber = [userInfo objectForKey:SenTestLineNumberKey];
- NSString *className = NSStringFromClass([self class]);
- if ([filename length] == 0) {
- filename = @"Unknown.m";
- }
- fprintf(stderr, "%s:%ld: error: -[%s %s] : %s\n",
- [filename UTF8String],
- (long)[lineNumber integerValue],
- [className UTF8String],
- [name UTF8String],
- [[exception reason] UTF8String]);
- fflush(stderr);
-}
-
-- (void)invokeTest {
- NSException *e = nil;
- @try {
- // Wrap things in autorelease pools because they may
- // have an STMacro in their dealloc which may get called
- // when the pool is cleaned up
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- // We don't log exceptions here, instead we let the person that called
- // this log the exception. This ensures they are only logged once but the
- // outer layers get the exceptions to report counts, etc.
- @try {
- [self setUp];
- @try {
- NSInvocation *invocation = [self invocation];
-#if GTM_IPHONE_SIMULATOR
- // We don't call [invocation invokeWithTarget:self]; because of
- // Radar 8081169: NSInvalidArgumentException can't be caught
- // It turns out that on iOS4 (and 3.2) exceptions thrown inside an
- // [invocation invoke] on the simulator cannot be caught.
- // http://openradar.appspot.com/8081169
- objc_msgSend(self, [invocation selector]);
-#else
- [invocation invokeWithTarget:self];
-#endif
- } @catch (NSException *exception) {
- e = [exception retain];
- }
- [self tearDown];
- } @catch (NSException *exception) {
- e = [exception retain];
- }
- [pool release];
- } @catch (NSException *exception) {
- e = [exception retain];
- }
- if (e) {
- [e autorelease];
- [e raise];
- }
-}
-
-- (void)tearDown {
-}
-
-- (NSString *)description {
- // This matches the description OCUnit would return to you
- return [NSString stringWithFormat:@"-[%@ %@]", [self class],
- NSStringFromSelector([self selector])];
-}
-
-// Used for sorting methods below
-static int MethodSort(id a, id b, void *context) {
- NSInvocation *invocationA = a;
- NSInvocation *invocationB = b;
- const char *nameA = sel_getName([invocationA selector]);
- const char *nameB = sel_getName([invocationB selector]);
- return strcmp(nameA, nameB);
-}
-
-
-+ (NSArray *)testInvocations {
- NSMutableArray *invocations = nil;
- // Need to walk all the way up the parent classes collecting methods (in case
- // a test is a subclass of another test).
- Class senTestCaseClass = [SenTestCase class];
- for (Class currentClass = self;
- currentClass && (currentClass != senTestCaseClass);
- currentClass = class_getSuperclass(currentClass)) {
- unsigned int methodCount;
- Method *methods = class_copyMethodList(currentClass, &methodCount);
- if (methods) {
- // This handles disposing of methods for us even if an exception should fly.
- [NSData dataWithBytesNoCopy:methods
- length:sizeof(Method) * methodCount];
- if (!invocations) {
- invocations = [NSMutableArray arrayWithCapacity:methodCount];
- }
- for (size_t i = 0; i < methodCount; ++i) {
- Method currMethod = methods[i];
- SEL sel = method_getName(currMethod);
- char *returnType = NULL;
- const char *name = sel_getName(sel);
- // If it starts with test, takes 2 args (target and sel) and returns
- // void run it.
- if (strstr(name, "test") == name) {
- returnType = method_copyReturnType(currMethod);
- if (returnType) {
- // This handles disposing of returnType for us even if an
- // exception should fly. Length +1 for the terminator, not that
- // the length really matters here, as we never reference inside
- // the data block.
- [NSData dataWithBytesNoCopy:returnType
- length:strlen(returnType) + 1];
- }
- }
- // TODO: If a test class is a subclass of another, and they reuse the
- // same selector name (ie-subclass overrides it), this current loop
- // and test here will cause cause it to get invoked twice. To fix this
- // the selector would have to be checked against all the ones already
- // added, so it only gets done once.
- if (returnType // True if name starts with "test"
- && strcmp(returnType, @encode(void)) == 0
- && method_getNumberOfArguments(currMethod) == 2) {
- NSMethodSignature *sig = [self instanceMethodSignatureForSelector:sel];
- NSInvocation *invocation
- = [NSInvocation invocationWithMethodSignature:sig];
- [invocation setSelector:sel];
- [invocations addObject:invocation];
- }
- }
- }
- }
- // Match SenTestKit and run everything in alphbetical order.
- [invocations sortUsingFunction:MethodSort context:nil];
- return invocations;
-}
-
-@end
-
-#endif // GTM_IPHONE_SDK && !GTM_IPHONE_USE_SENTEST
-
-@implementation GTMTestCase : SenTestCase
-- (void)invokeTest {
- NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
- Class devLogClass = NSClassFromString(@"GTMUnitTestDevLog");
- if (devLogClass) {
- [devLogClass performSelector:@selector(enableTracking)];
- [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
-
- }
- [super invokeTest];
- if (devLogClass) {
- [devLogClass performSelector:@selector(verifyNoMoreLogsExpected)];
- [devLogClass performSelector:@selector(disableTracking)];
- }
- [localPool drain];
-}
-
-+ (BOOL)isAbstractTestCase {
- NSString *name = NSStringFromClass(self);
- return [name rangeOfString:@"AbstractTest"].location != NSNotFound;
-}
-
-+ (NSArray *)testInvocations {
- NSArray *invocations = nil;
- if (![self isAbstractTestCase]) {
- invocations = [super testInvocations];
- }
- return invocations;
-}
-
-@end
diff --git a/toolkit/crashreporter/google-breakpad/src/common/md5.cc b/toolkit/crashreporter/google-breakpad/src/common/md5.cc
deleted file mode 100644
index a0d9a1bdd..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/md5.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-#include <string.h>
-
-#include "common/md5.h"
-
-namespace google_breakpad {
-
-#ifndef WORDS_BIGENDIAN
-#define byteReverse(buf, len) /* Nothing */
-#else
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse(unsigned char *buf, unsigned longs)
-{
- u32 t;
- do {
- t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(u32 *) buf = t;
- buf += 4;
- } while (--longs);
-}
-#endif
-
-static void MD5Transform(u32 buf[4], u32 const in[16]);
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-void MD5Init(struct MD5Context *ctx)
-{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
-
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void MD5Update(struct MD5Context *ctx, unsigned char const *buf, size_t len)
-{
- u32 t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
-
- t = 64 - t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (u32 *) ctx->in);
- buf += t;
- len -= t;
- }
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (u32 *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
-{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (u32 *) ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- ((u32 *) ctx->in)[14] = ctx->bits[0];
- ((u32 *) ctx->in)[15] = ctx->bits[1];
-
- MD5Transform(ctx->buf, (u32 *) ctx->in);
- byteReverse((unsigned char *) ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
-}
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(u32 buf[4], u32 const in[16])
-{
- u32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-} // namespace google_breakpad
-
diff --git a/toolkit/crashreporter/google-breakpad/src/common/md5.h b/toolkit/crashreporter/google-breakpad/src/common/md5.h
deleted file mode 100644
index 2ab0ab95a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/md5.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2007 Google Inc. All Rights Reserved.
-// Author: liuli@google.com (Liu Li)
-#ifndef COMMON_MD5_H__
-#define COMMON_MD5_H__
-
-#include <stdint.h>
-
-namespace google_breakpad {
-
-typedef uint32_t u32;
-typedef uint8_t u8;
-
-struct MD5Context {
- u32 buf[4];
- u32 bits[2];
- u8 in[64];
-};
-
-void MD5Init(struct MD5Context *ctx);
-
-void MD5Update(struct MD5Context *ctx, unsigned char const *buf, size_t len);
-
-void MD5Final(unsigned char digest[16], struct MD5Context *ctx);
-
-} // namespace google_breakpad
-
-#endif // COMMON_MD5_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/memory.h b/toolkit/crashreporter/google-breakpad/src/common/memory.h
deleted file mode 100644
index 9158b50c8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/memory.h
+++ /dev/null
@@ -1,249 +0,0 @@
-// 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.
-
-#ifndef GOOGLE_BREAKPAD_COMMON_MEMORY_H_
-#define GOOGLE_BREAKPAD_COMMON_MEMORY_H_
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/mman.h>
-
-#include <memory>
-#include <vector>
-
-#if defined(MEMORY_SANITIZER)
-#include <sanitizer/msan_interface.h>
-#endif
-
-#ifdef __APPLE__
-#define sys_mmap mmap
-#define sys_munmap munmap
-#define MAP_ANONYMOUS MAP_ANON
-#else
-#include "third_party/lss/linux_syscall_support.h"
-#endif
-
-namespace google_breakpad {
-
-// This is very simple allocator which fetches pages from the kernel directly.
-// Thus, it can be used even when the heap may be corrupted.
-//
-// There is no free operation. The pages are only freed when the object is
-// destroyed.
-class PageAllocator {
- public:
- PageAllocator()
- : page_size_(getpagesize()),
- last_(NULL),
- current_page_(NULL),
- page_offset_(0),
- pages_allocated_(0) {
- }
-
- ~PageAllocator() {
- FreeAll();
- }
-
- void *Alloc(size_t bytes) {
- if (!bytes)
- return NULL;
-
- if (current_page_ && page_size_ - page_offset_ >= bytes) {
- uint8_t *const ret = current_page_ + page_offset_;
- page_offset_ += bytes;
- if (page_offset_ == page_size_) {
- page_offset_ = 0;
- current_page_ = NULL;
- }
-
- return ret;
- }
-
- const size_t pages =
- (bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_;
- uint8_t *const ret = GetNPages(pages);
- if (!ret)
- return NULL;
-
- page_offset_ =
- (page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) %
- page_size_;
- current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL;
-
- return ret + sizeof(PageHeader);
- }
-
- // Checks whether the page allocator owns the passed-in pointer.
- // This method exists for testing pursposes only.
- bool OwnsPointer(const void* p) {
- for (PageHeader* header = last_; header; header = header->next) {
- const char* current = reinterpret_cast<char*>(header);
- if ((p >= current) && (p < current + header->num_pages * page_size_))
- return true;
- }
-
- return false;
- }
-
- unsigned long pages_allocated() { return pages_allocated_; }
-
- private:
- uint8_t *GetNPages(size_t num_pages) {
- void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (a == MAP_FAILED)
- return NULL;
-
-#if defined(MEMORY_SANITIZER)
- // We need to indicate to MSan that memory allocated through sys_mmap is
- // initialized, since linux_syscall_support.h doesn't have MSan hooks.
- __msan_unpoison(a, page_size_ * num_pages);
-#endif
-
- struct PageHeader *header = reinterpret_cast<PageHeader*>(a);
- header->next = last_;
- header->num_pages = num_pages;
- last_ = header;
-
- pages_allocated_ += num_pages;
-
- return reinterpret_cast<uint8_t*>(a);
- }
-
- void FreeAll() {
- PageHeader *next;
-
- for (PageHeader *cur = last_; cur; cur = next) {
- next = cur->next;
- sys_munmap(cur, cur->num_pages * page_size_);
- }
- }
-
- struct PageHeader {
- PageHeader *next; // pointer to the start of the next set of pages.
- size_t num_pages; // the number of pages in this set.
- };
-
- const size_t page_size_;
- PageHeader *last_;
- uint8_t *current_page_;
- size_t page_offset_;
- unsigned long pages_allocated_;
-};
-
-// Wrapper to use with STL containers
-template <typename T>
-struct PageStdAllocator : public std::allocator<T> {
- typedef typename std::allocator<T>::pointer pointer;
- typedef typename std::allocator<T>::size_type size_type;
-
- explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator),
- stackdata_(NULL),
- stackdata_size_(0)
- {}
-
- template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other)
- : allocator_(other.allocator_),
- stackdata_(nullptr),
- stackdata_size_(0)
- {}
-
- explicit PageStdAllocator(PageAllocator& allocator,
- pointer stackdata,
- size_type stackdata_size) : allocator_(allocator),
- stackdata_(stackdata),
- stackdata_size_(stackdata_size)
- {}
-
- inline pointer allocate(size_type n, const void* = 0) {
- const size_type size = sizeof(T) * n;
- if (size <= stackdata_size_) {
- return stackdata_;
- }
- return static_cast<pointer>(allocator_.Alloc(size));
- }
-
- inline void deallocate(pointer, size_type) {
- // The PageAllocator doesn't free.
- }
-
- template <typename U> struct rebind {
- typedef PageStdAllocator<U> other;
- };
-
- private:
- // Silly workaround for the gcc from Android's ndk (gcc 4.6), which will
- // otherwise complain that `other.allocator_` is private in the constructor
- // code.
- template<typename Other> friend struct PageStdAllocator;
-
- PageAllocator& allocator_;
- pointer stackdata_;
- size_type stackdata_size_;
-};
-
-// A wasteful vector is a std::vector, except that it allocates memory from a
-// PageAllocator. It's wasteful because, when resizing, it always allocates a
-// whole new array since the PageAllocator doesn't support realloc.
-template<class T>
-class wasteful_vector : public std::vector<T, PageStdAllocator<T> > {
- public:
- wasteful_vector(PageAllocator* allocator, unsigned size_hint = 16)
- : std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) {
- std::vector<T, PageStdAllocator<T> >::reserve(size_hint);
- }
- protected:
- wasteful_vector(PageStdAllocator<T> allocator)
- : std::vector<T, PageStdAllocator<T> >(allocator) {}
-};
-
-// auto_wasteful_vector allocates space on the stack for N entries to avoid
-// using the PageAllocator for small data, while still allowing for larger data.
-template<class T, unsigned int N>
-class auto_wasteful_vector : public wasteful_vector<T> {
- T stackdata_[N];
- public:
- auto_wasteful_vector(PageAllocator* allocator)
- : wasteful_vector<T>(
- PageStdAllocator<T>(*allocator,
- &stackdata_[0],
- sizeof(stackdata_))) {
- std::vector<T, PageStdAllocator<T> >::reserve(N);
- }
-};
-
-} // namespace google_breakpad
-
-inline void* operator new(size_t nbytes,
- google_breakpad::PageAllocator& allocator) {
- return allocator.Alloc(nbytes);
-}
-
-#endif // GOOGLE_BREAKPAD_COMMON_MEMORY_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/memory_range.h b/toolkit/crashreporter/google-breakpad/src/common/memory_range.h
deleted file mode 100644
index 41dd2da62..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/memory_range.h
+++ /dev/null
@@ -1,145 +0,0 @@
-// 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.
-
-// memory_range.h: Define the google_breakpad::MemoryRange class, which
-// is a lightweight wrapper with a pointer and a length to encapsulate
-// a contiguous range of memory.
-
-#ifndef COMMON_MEMORY_RANGE_H_
-#define COMMON_MEMORY_RANGE_H_
-
-#include <stddef.h>
-
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-
-// A lightweight wrapper with a pointer and a length to encapsulate a
-// contiguous range of memory. It provides helper methods for checked
-// access of a subrange of the memory. Its implemementation does not
-// allocate memory or call into libc functions, and is thus safer to use
-// in a crashed environment.
-class MemoryRange {
- public:
- MemoryRange() : data_(NULL), length_(0) {}
-
- MemoryRange(const void* data, size_t length) {
- Set(data, length);
- }
-
- // Returns true if this memory range contains no data.
- bool IsEmpty() const {
- // Set() guarantees that |length_| is zero if |data_| is NULL.
- return length_ == 0;
- }
-
- // Resets to an empty range.
- void Reset() {
- data_ = NULL;
- length_ = 0;
- }
-
- // Sets this memory range to point to |data| and its length to |length|.
- void Set(const void* data, size_t length) {
- data_ = reinterpret_cast<const uint8_t*>(data);
- // Always set |length_| to zero if |data_| is NULL.
- length_ = data ? length : 0;
- }
-
- // Returns true if this range covers a subrange of |sub_length| bytes
- // at |sub_offset| bytes of this memory range, or false otherwise.
- bool Covers(size_t sub_offset, size_t sub_length) const {
- // The following checks verify that:
- // 1. sub_offset is within [ 0 .. length_ - 1 ]
- // 2. sub_offset + sub_length is within
- // [ sub_offset .. length_ ]
- return sub_offset < length_ &&
- sub_offset + sub_length >= sub_offset &&
- sub_offset + sub_length <= length_;
- }
-
- // Returns a raw data pointer to a subrange of |sub_length| bytes at
- // |sub_offset| bytes of this memory range, or NULL if the subrange
- // is out of bounds.
- const void* GetData(size_t sub_offset, size_t sub_length) const {
- return Covers(sub_offset, sub_length) ? (data_ + sub_offset) : NULL;
- }
-
- // Same as the two-argument version of GetData() but uses sizeof(DataType)
- // as the subrange length and returns an |DataType| pointer for convenience.
- template <typename DataType>
- const DataType* GetData(size_t sub_offset) const {
- return reinterpret_cast<const DataType*>(
- GetData(sub_offset, sizeof(DataType)));
- }
-
- // Returns a raw pointer to the |element_index|-th element of an array
- // of elements of length |element_size| starting at |sub_offset| bytes
- // of this memory range, or NULL if the element is out of bounds.
- const void* GetArrayElement(size_t element_offset,
- size_t element_size,
- unsigned element_index) const {
- size_t sub_offset = element_offset + element_index * element_size;
- return GetData(sub_offset, element_size);
- }
-
- // Same as the three-argument version of GetArrayElement() but deduces
- // the element size using sizeof(ElementType) and returns an |ElementType|
- // pointer for convenience.
- template <typename ElementType>
- const ElementType* GetArrayElement(size_t element_offset,
- unsigned element_index) const {
- return reinterpret_cast<const ElementType*>(
- GetArrayElement(element_offset, sizeof(ElementType), element_index));
- }
-
- // Returns a subrange of |sub_length| bytes at |sub_offset| bytes of
- // this memory range, or an empty range if the subrange is out of bounds.
- MemoryRange Subrange(size_t sub_offset, size_t sub_length) const {
- return Covers(sub_offset, sub_length) ?
- MemoryRange(data_ + sub_offset, sub_length) : MemoryRange();
- }
-
- // Returns a pointer to the beginning of this memory range.
- const uint8_t* data() const { return data_; }
-
- // Returns the length, in bytes, of this memory range.
- size_t length() const { return length_; }
-
- private:
- // Pointer to the beginning of this memory range.
- const uint8_t* data_;
-
- // Length, in bytes, of this memory range.
- size_t length_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_MEMORY_RANGE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/memory_range_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/memory_range_unittest.cc
deleted file mode 100644
index f6cf8c8b2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/memory_range_unittest.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-// 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.
-
-// memory_range_unittest.cc: Unit tests for google_breakpad::MemoryRange.
-
-#include "breakpad_googletest_includes.h"
-#include "common/memory_range.h"
-
-using google_breakpad::MemoryRange;
-using testing::Message;
-
-namespace {
-
-const uint32_t kBuffer[10] = { 0 };
-const size_t kBufferSize = sizeof(kBuffer);
-const uint8_t* kBufferPointer = reinterpret_cast<const uint8_t*>(kBuffer);
-
-// Test vectors for verifying Covers, GetData, and Subrange.
-const struct {
- bool valid;
- size_t offset;
- size_t length;
-} kSubranges[] = {
- { true, 0, 0 },
- { true, 0, 2 },
- { true, 0, kBufferSize },
- { true, 2, 0 },
- { true, 2, 4 },
- { true, 2, kBufferSize - 2 },
- { true, kBufferSize - 1, 1 },
- { false, kBufferSize, 0 },
- { false, kBufferSize, static_cast<size_t>(-1) },
- { false, kBufferSize + 1, 0 },
- { false, static_cast<size_t>(-1), 2 },
- { false, 1, kBufferSize },
- { false, kBufferSize - 1, 2 },
- { false, 0, static_cast<size_t>(-1) },
- { false, 1, static_cast<size_t>(-1) },
-};
-const size_t kNumSubranges = sizeof(kSubranges) / sizeof(kSubranges[0]);
-
-// Test vectors for verifying GetArrayElement.
-const struct {
- size_t offset;
- size_t size;
- size_t index;
- const void* const pointer;
-} kElements[] = {
- // Valid array elemenets
- { 0, 1, 0, kBufferPointer },
- { 0, 1, 1, kBufferPointer + 1 },
- { 0, 1, kBufferSize - 1, kBufferPointer + kBufferSize - 1 },
- { 0, 2, 1, kBufferPointer + 2 },
- { 0, 4, 2, kBufferPointer + 8 },
- { 0, 4, 9, kBufferPointer + 36 },
- { kBufferSize - 1, 1, 0, kBufferPointer + kBufferSize - 1 },
- // Invalid array elemenets
- { 0, 1, kBufferSize, NULL },
- { 0, 4, 10, NULL },
- { kBufferSize - 1, 1, 1, NULL },
- { kBufferSize - 1, 2, 0, NULL },
- { kBufferSize, 1, 0, NULL },
-};
-const size_t kNumElements = sizeof(kElements) / sizeof(kElements[0]);
-
-} // namespace
-
-TEST(MemoryRangeTest, DefaultConstructor) {
- MemoryRange range;
- EXPECT_EQ(NULL, range.data());
- EXPECT_EQ(0U, range.length());
-}
-
-TEST(MemoryRangeTest, ConstructorWithDataAndLength) {
- MemoryRange range(kBuffer, kBufferSize);
- EXPECT_EQ(kBufferPointer, range.data());
- EXPECT_EQ(kBufferSize, range.length());
-}
-
-TEST(MemoryRangeTest, Reset) {
- MemoryRange range;
- range.Reset();
- EXPECT_EQ(NULL, range.data());
- EXPECT_EQ(0U, range.length());
-
- range.Set(kBuffer, kBufferSize);
- EXPECT_EQ(kBufferPointer, range.data());
- EXPECT_EQ(kBufferSize, range.length());
-
- range.Reset();
- EXPECT_EQ(NULL, range.data());
- EXPECT_EQ(0U, range.length());
-}
-
-TEST(MemoryRangeTest, Set) {
- MemoryRange range;
- range.Set(kBuffer, kBufferSize);
- EXPECT_EQ(kBufferPointer, range.data());
- EXPECT_EQ(kBufferSize, range.length());
-
- range.Set(NULL, 0);
- EXPECT_EQ(NULL, range.data());
- EXPECT_EQ(0U, range.length());
-}
-
-TEST(MemoryRangeTest, SubrangeOfEmptyMemoryRange) {
- MemoryRange range;
- MemoryRange subrange = range.Subrange(0, 10);
- EXPECT_EQ(NULL, subrange.data());
- EXPECT_EQ(0U, subrange.length());
-}
-
-TEST(MemoryRangeTest, SubrangeAndGetData) {
- MemoryRange range(kBuffer, kBufferSize);
- for (size_t i = 0; i < kNumSubranges; ++i) {
- bool valid = kSubranges[i].valid;
- size_t sub_offset = kSubranges[i].offset;
- size_t sub_length = kSubranges[i].length;
- SCOPED_TRACE(Message() << "offset=" << sub_offset
- << ", length=" << sub_length);
-
- MemoryRange subrange = range.Subrange(sub_offset, sub_length);
- if (valid) {
- EXPECT_TRUE(range.Covers(sub_offset, sub_length));
- EXPECT_EQ(kBufferPointer + sub_offset,
- range.GetData(sub_offset, sub_length));
- EXPECT_EQ(kBufferPointer + sub_offset, subrange.data());
- EXPECT_EQ(sub_length, subrange.length());
- } else {
- EXPECT_FALSE(range.Covers(sub_offset, sub_length));
- EXPECT_EQ(NULL, range.GetData(sub_offset, sub_length));
- EXPECT_EQ(NULL, subrange.data());
- EXPECT_EQ(0U, subrange.length());
- }
- }
-}
-
-TEST(MemoryRangeTest, GetDataWithTemplateType) {
- MemoryRange range(kBuffer, kBufferSize);
- const char* char_pointer = range.GetData<char>(0);
- EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
- const int* int_pointer = range.GetData<int>(0);
- EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
-}
-
-TEST(MemoryRangeTest, GetArrayElement) {
- MemoryRange range(kBuffer, kBufferSize);
- for (size_t i = 0; i < kNumElements; ++i) {
- size_t element_offset = kElements[i].offset;
- size_t element_size = kElements[i].size;
- unsigned element_index = kElements[i].index;
- const void* const element_pointer = kElements[i].pointer;
- SCOPED_TRACE(Message() << "offset=" << element_offset
- << ", size=" << element_size
- << ", index=" << element_index);
- EXPECT_EQ(element_pointer, range.GetArrayElement(
- element_offset, element_size, element_index));
- }
-}
-
-TEST(MemoryRangeTest, GetArrayElmentWithTemplateType) {
- MemoryRange range(kBuffer, kBufferSize);
- const char* char_pointer = range.GetArrayElement<char>(0, 0);
- EXPECT_EQ(reinterpret_cast<const char*>(kBufferPointer), char_pointer);
- const int* int_pointer = range.GetArrayElement<int>(0, 0);
- EXPECT_EQ(reinterpret_cast<const int*>(kBufferPointer), int_pointer);
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/memory_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/memory_unittest.cc
deleted file mode 100644
index 8d2494c23..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/memory_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// 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.
-
-#include "breakpad_googletest_includes.h"
-#include "common/memory.h"
-
-using namespace google_breakpad;
-
-namespace {
-typedef testing::Test PageAllocatorTest;
-}
-
-TEST(PageAllocatorTest, Setup) {
- PageAllocator allocator;
- EXPECT_EQ(0U, allocator.pages_allocated());
-}
-
-TEST(PageAllocatorTest, SmallObjects) {
- PageAllocator allocator;
-
- EXPECT_EQ(0U, allocator.pages_allocated());
- for (unsigned i = 1; i < 1024; ++i) {
- uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
- ASSERT_FALSE(p == NULL);
- memset(p, 0, i);
- }
-}
-
-TEST(PageAllocatorTest, LargeObject) {
- PageAllocator allocator;
-
- EXPECT_EQ(0U, allocator.pages_allocated());
- uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(10000));
- ASSERT_FALSE(p == NULL);
- EXPECT_EQ(3U, allocator.pages_allocated());
- for (unsigned i = 1; i < 10; ++i) {
- uint8_t *p = reinterpret_cast<uint8_t*>(allocator.Alloc(i));
- ASSERT_FALSE(p == NULL);
- memset(p, 0, i);
- }
-}
-
-namespace {
-typedef testing::Test WastefulVectorTest;
-}
-
-TEST(WastefulVectorTest, Setup) {
- PageAllocator allocator_;
- wasteful_vector<int> v(&allocator_);
- ASSERT_TRUE(v.empty());
- ASSERT_EQ(v.size(), 0u);
-}
-
-TEST(WastefulVectorTest, Simple) {
- PageAllocator allocator_;
- EXPECT_EQ(0U, allocator_.pages_allocated());
- wasteful_vector<unsigned> v(&allocator_);
-
- for (unsigned i = 0; i < 256; ++i) {
- v.push_back(i);
- ASSERT_EQ(i, v.back());
- ASSERT_EQ(&v.back(), &v[i]);
- }
- ASSERT_FALSE(v.empty());
- ASSERT_EQ(v.size(), 256u);
- EXPECT_EQ(1U, allocator_.pages_allocated());
- for (unsigned i = 0; i < 256; ++i)
- ASSERT_EQ(v[i], i);
-}
-
-TEST(WastefulVectorTest, UsesPageAllocator) {
- PageAllocator allocator_;
- wasteful_vector<unsigned> v(&allocator_);
- EXPECT_EQ(1U, allocator_.pages_allocated());
-
- v.push_back(1);
- ASSERT_TRUE(allocator_.OwnsPointer(&v[0]));
-}
-
-TEST(WastefulVectorTest, AutoWastefulVector) {
- PageAllocator allocator_;
- EXPECT_EQ(0U, allocator_.pages_allocated());
-
- auto_wasteful_vector<unsigned, 4> v(&allocator_);
- EXPECT_EQ(0U, allocator_.pages_allocated());
-
- v.push_back(1);
- EXPECT_EQ(0U, allocator_.pages_allocated());
- EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
-
- v.resize(4);
- EXPECT_EQ(0U, allocator_.pages_allocated());
- EXPECT_FALSE(allocator_.OwnsPointer(&v[0]));
-
- v.resize(10);
- EXPECT_EQ(1U, allocator_.pages_allocated());
- EXPECT_TRUE(allocator_.OwnsPointer(&v[0]));
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h b/toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h
deleted file mode 100644
index 5a7d5a6a8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/minidump_type_helper.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2014, 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_COMMON_MINIDUMP_TYPE_HELPER_H_
-#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
-
-#include <stdint.h>
-
-#include "google_breakpad/common/minidump_format.h"
-
-namespace google_breakpad {
-
-template <size_t>
-struct MDTypeHelper;
-
-template <>
-struct MDTypeHelper<sizeof(uint32_t)> {
- typedef MDRawDebug32 MDRawDebug;
- typedef MDRawLinkMap32 MDRawLinkMap;
-};
-
-template <>
-struct MDTypeHelper<sizeof(uint64_t)> {
- typedef MDRawDebug64 MDRawDebug;
- typedef MDRawLinkMap64 MDRawLinkMap;
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_COMMON_MINIDUMP_TYPE_HELPER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/module.cc b/toolkit/crashreporter/google-breakpad/src/common/module.cc
deleted file mode 100644
index e701f1b59..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/module.cc
+++ /dev/null
@@ -1,348 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// module.cc: Implement google_breakpad::Module. See module.h.
-
-#include "common/module.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <iostream>
-#include <utility>
-
-namespace google_breakpad {
-
-using std::dec;
-using std::endl;
-using std::hex;
-
-
-Module::Module(const string &name, const string &os,
- const string &architecture, const string &id,
- const string &code_id /* = "" */) :
- name_(name),
- os_(os),
- architecture_(architecture),
- id_(id),
- code_id_(code_id),
- load_address_(0) { }
-
-Module::~Module() {
- for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
- delete it->second;
- for (FunctionSet::iterator it = functions_.begin();
- it != functions_.end(); ++it) {
- delete *it;
- }
- for (StackFrameEntrySet::iterator it = stack_frame_entries_.begin();
- it != stack_frame_entries_.end(); ++it) {
- delete *it;
- }
- for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
- delete *it;
-}
-
-void Module::SetLoadAddress(Address address) {
- load_address_ = address;
-}
-
-void Module::AddFunction(Function *function) {
- // FUNC lines must not hold an empty name, so catch the problem early if
- // callers try to add one.
- assert(!function->name.empty());
-
- // FUNCs are better than PUBLICs as they come with sizes, so remove an extern
- // with the same address if present.
- Extern ext(function->address);
- ExternSet::iterator it_ext = externs_.find(&ext);
- if (it_ext == externs_.end() &&
- architecture_ == "arm" &&
- (function->address & 0x1) == 0) {
- // ARM THUMB functions have bit 0 set. ARM64 does not have THUMB.
- Extern arm_thumb_ext(function->address | 0x1);
- it_ext = externs_.find(&arm_thumb_ext);
- }
- if (it_ext != externs_.end()) {
- delete *it_ext;
- externs_.erase(it_ext);
- }
-#if _DEBUG
- {
- // There should be no other PUBLIC symbols that overlap with the function.
- Extern debug_ext(function->address);
- ExternSet::iterator it_debug = externs_.lower_bound(&ext);
- assert(it_debug == externs_.end() ||
- (*it_debug)->address >= function->address + function->size);
- }
-#endif
-
- std::pair<FunctionSet::iterator,bool> ret = functions_.insert(function);
- if (!ret.second && (*ret.first != function)) {
- // Free the duplicate that was not inserted because this Module
- // now owns it.
- delete function;
- }
-}
-
-void Module::AddFunctions(vector<Function *>::iterator begin,
- vector<Function *>::iterator end) {
- for (vector<Function *>::iterator it = begin; it != end; ++it)
- AddFunction(*it);
-}
-
-void Module::AddStackFrameEntry(StackFrameEntry* stack_frame_entry) {
- std::pair<StackFrameEntrySet::iterator,bool> ret =
- stack_frame_entries_.insert(stack_frame_entry);
- if (!ret.second) {
- // Free the duplicate that was not inserted because this Module
- // now owns it.
- delete stack_frame_entry;
- }
-}
-
-void Module::AddExtern(Extern *ext) {
- std::pair<ExternSet::iterator,bool> ret = externs_.insert(ext);
- if (!ret.second) {
- // Free the duplicate that was not inserted because this Module
- // now owns it.
- delete ext;
- }
-}
-
-void Module::GetFunctions(vector<Function *> *vec,
- vector<Function *>::iterator i) {
- vec->insert(i, functions_.begin(), functions_.end());
-}
-
-void Module::GetExterns(vector<Extern *> *vec,
- vector<Extern *>::iterator i) {
- vec->insert(i, externs_.begin(), externs_.end());
-}
-
-Module::File *Module::FindFile(const string &name) {
- // A tricky bit here. The key of each map entry needs to be a
- // pointer to the entry's File's name string. This means that we
- // can't do the initial lookup with any operation that would create
- // an empty entry for us if the name isn't found (like, say,
- // operator[] or insert do), because such a created entry's key will
- // be a pointer the string passed as our argument. Since the key of
- // a map's value type is const, we can't fix it up once we've
- // created our file. lower_bound does the lookup without doing an
- // insertion, and returns a good hint iterator to pass to insert.
- // Our "destiny" is where we belong, whether we're there or not now.
- FileByNameMap::iterator destiny = files_.lower_bound(&name);
- if (destiny == files_.end()
- || *destiny->first != name) { // Repeated string comparison, boo hoo.
- File *file = new File(name);
- file->source_id = -1;
- destiny = files_.insert(destiny,
- FileByNameMap::value_type(&file->name, file));
- }
- return destiny->second;
-}
-
-Module::File *Module::FindFile(const char *name) {
- string name_string = name;
- return FindFile(name_string);
-}
-
-Module::File *Module::FindExistingFile(const string &name) {
- FileByNameMap::iterator it = files_.find(&name);
- return (it == files_.end()) ? NULL : it->second;
-}
-
-void Module::GetFiles(vector<File *> *vec) {
- vec->clear();
- for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
- vec->push_back(it->second);
-}
-
-void Module::GetStackFrameEntries(vector<StackFrameEntry*>* vec) const {
- vec->clear();
- vec->insert(vec->begin(), stack_frame_entries_.begin(),
- stack_frame_entries_.end());
-}
-
-Module::StackFrameEntry* Module::FindStackFrameEntryByAddress(Address address) {
- StackFrameEntry search;
- search.address = address;
- StackFrameEntrySet::iterator it = stack_frame_entries_.upper_bound(&search);
-
- if (it == stack_frame_entries_.begin())
- return NULL;
-
- it--;
- if ((*it)->address <= address && address < (*it)->address + (*it)->size)
- return *it;
-
- return NULL;
-}
-
-void Module::AssignSourceIds() {
- // First, give every source file an id of -1.
- for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); ++file_it) {
- file_it->second->source_id = -1;
- }
-
- // Next, mark all files actually cited by our functions' line number
- // info, by setting each one's source id to zero.
- for (FunctionSet::const_iterator func_it = functions_.begin();
- func_it != functions_.end(); ++func_it) {
- Function *func = *func_it;
- for (vector<Line>::iterator line_it = func->lines.begin();
- line_it != func->lines.end(); ++line_it)
- line_it->file->source_id = 0;
- }
-
- // Finally, assign source ids to those files that have been marked.
- // We could have just assigned source id numbers while traversing
- // the line numbers, but doing it this way numbers the files in
- // lexicographical order by name, which is neat.
- int next_source_id = 0;
- for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); ++file_it) {
- if (!file_it->second->source_id)
- file_it->second->source_id = next_source_id++;
- }
-}
-
-bool Module::ReportError() {
- fprintf(stderr, "error writing symbol file: %s\n",
- strerror(errno));
- return false;
-}
-
-bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
- for (RuleMap::const_iterator it = rule_map.begin();
- it != rule_map.end(); ++it) {
- if (it != rule_map.begin())
- stream << ' ';
- stream << it->first << ": " << it->second;
- }
- return stream.good();
-}
-
-bool Module::Write(std::ostream &stream, SymbolData symbol_data) {
- stream << "MODULE " << os_ << " " << architecture_ << " "
- << id_ << " " << name_ << endl;
- if (!stream.good())
- return ReportError();
-
- if (!code_id_.empty()) {
- stream << "INFO CODE_ID " << code_id_ << endl;
- }
-
- if (symbol_data != ONLY_CFI) {
- AssignSourceIds();
-
- // Write out files.
- for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); ++file_it) {
- File *file = file_it->second;
- if (file->source_id >= 0) {
- stream << "FILE " << file->source_id << " " << file->name << endl;
- if (!stream.good())
- return ReportError();
- }
- }
-
- // Write out functions and their lines.
- for (FunctionSet::const_iterator func_it = functions_.begin();
- func_it != functions_.end(); ++func_it) {
- Function *func = *func_it;
- stream << "FUNC " << hex
- << (func->address - load_address_) << " "
- << func->size << " "
- << func->parameter_size << " "
- << func->name << dec << endl;
- if (!stream.good())
- return ReportError();
-
- for (vector<Line>::iterator line_it = func->lines.begin();
- line_it != func->lines.end(); ++line_it) {
- stream << hex
- << (line_it->address - load_address_) << " "
- << line_it->size << " "
- << dec
- << line_it->number << " "
- << line_it->file->source_id << endl;
- if (!stream.good())
- return ReportError();
- }
- }
-
- // Write out 'PUBLIC' records.
- for (ExternSet::const_iterator extern_it = externs_.begin();
- extern_it != externs_.end(); ++extern_it) {
- Extern *ext = *extern_it;
- stream << "PUBLIC " << hex
- << (ext->address - load_address_) << " 0 "
- << ext->name << dec << endl;
- }
- }
-
- if (symbol_data != NO_CFI) {
- // Write out 'STACK CFI INIT' and 'STACK CFI' records.
- StackFrameEntrySet::const_iterator frame_it;
- for (frame_it = stack_frame_entries_.begin();
- frame_it != stack_frame_entries_.end(); ++frame_it) {
- StackFrameEntry *entry = *frame_it;
- stream << "STACK CFI INIT " << hex
- << (entry->address - load_address_) << " "
- << entry->size << " " << dec;
- if (!stream.good()
- || !WriteRuleMap(entry->initial_rules, stream))
- return ReportError();
-
- stream << endl;
-
- // Write out this entry's delta rules as 'STACK CFI' records.
- for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
- delta_it != entry->rule_changes.end(); ++delta_it) {
- stream << "STACK CFI " << hex
- << (delta_it->first - load_address_) << " " << dec;
- if (!stream.good()
- || !WriteRuleMap(delta_it->second, stream))
- return ReportError();
-
- stream << endl;
- }
- }
- }
-
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/module.h b/toolkit/crashreporter/google-breakpad/src/common/module.h
deleted file mode 100644
index 305f94579..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/module.h
+++ /dev/null
@@ -1,351 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// module.h: Define google_breakpad::Module. A Module holds debugging
-// information, and can write that information out as a Breakpad
-// symbol file.
-
-#ifndef COMMON_LINUX_MODULE_H__
-#define COMMON_LINUX_MODULE_H__
-
-#include <iostream>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "common/symbol_data.h"
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-
-using std::set;
-using std::vector;
-using std::map;
-
-// A Module represents the contents of a module, and supports methods
-// for adding information produced by parsing STABS or DWARF data
-// --- possibly both from the same file --- and then writing out the
-// unified contents as a Breakpad-format symbol file.
-class Module {
- public:
- // The type of addresses and sizes in a symbol table.
- typedef uint64_t Address;
- struct File;
- struct Function;
- struct Line;
- struct Extern;
-
- // Addresses appearing in File, Function, and Line structures are
- // absolute, not relative to the the module's load address. That
- // is, if the module were loaded at its nominal load address, the
- // addresses would be correct.
-
- // A source file.
- struct File {
- explicit File(const string &name_input) : name(name_input), source_id(0) {}
-
- // The name of the source file.
- const string name;
-
- // The file's source id. The Write member function clears this
- // field and assigns source ids a fresh, so any value placed here
- // before calling Write will be lost.
- int source_id;
- };
-
- // A function.
- struct Function {
- Function(const string &name_input, const Address &address_input) :
- name(name_input), address(address_input), size(0), parameter_size(0) {}
-
- // For sorting by address. (Not style-guide compliant, but it's
- // stupid not to put this in the struct.)
- static bool CompareByAddress(const Function *x, const Function *y) {
- return x->address < y->address;
- }
-
- // The function's name.
- const string name;
-
- // The start address and length of the function's code.
- const Address address;
- Address size;
-
- // The function's parameter size.
- Address parameter_size;
-
- // Source lines belonging to this function, sorted by increasing
- // address.
- vector<Line> lines;
- };
-
- // A source line.
- struct Line {
- // For sorting by address. (Not style-guide compliant, but it's
- // stupid not to put this in the struct.)
- static bool CompareByAddress(const Module::Line &x, const Module::Line &y) {
- return x.address < y.address;
- }
-
- Address address, size; // The address and size of the line's code.
- File *file; // The source file.
- int number; // The source line number.
- };
-
- // An exported symbol.
- struct Extern {
- explicit Extern(const Address &address_input) : address(address_input) {}
- const Address address;
- string name;
- };
-
- // A map from register names to postfix expressions that recover
- // their their values. This can represent a complete set of rules to
- // follow at some address, or a set of changes to be applied to an
- // extant set of rules.
- typedef map<string, string> RuleMap;
-
- // A map from addresses to RuleMaps, representing changes that take
- // effect at given addresses.
- typedef map<Address, RuleMap> RuleChangeMap;
-
- // A range of 'STACK CFI' stack walking information. An instance of
- // this structure corresponds to a 'STACK CFI INIT' record and the
- // subsequent 'STACK CFI' records that fall within its range.
- struct StackFrameEntry {
- // The starting address and number of bytes of machine code this
- // entry covers.
- Address address, size;
-
- // The initial register recovery rules, in force at the starting
- // address.
- RuleMap initial_rules;
-
- // A map from addresses to rule changes. To find the rules in
- // force at a given address, start with initial_rules, and then
- // apply the changes given in this map for all addresses up to and
- // including the address you're interested in.
- RuleChangeMap rule_changes;
- };
-
- struct FunctionCompare {
- bool operator() (const Function *lhs,
- const Function *rhs) const {
- if (lhs->address == rhs->address)
- return lhs->name < rhs->name;
- return lhs->address < rhs->address;
- }
- };
-
- struct ExternCompare {
- bool operator() (const Extern *lhs,
- const Extern *rhs) const {
- return lhs->address < rhs->address;
- }
- };
-
- struct StackFrameEntryCompare {
- bool operator() (const StackFrameEntry* lhs,
- const StackFrameEntry* rhs) const {
- return lhs->address < rhs->address;
- }
- };
-
- // Create a new module with the given name, operating system,
- // architecture, and ID string.
- Module(const string &name, const string &os, const string &architecture,
- const string &id, const string &code_id = "");
- ~Module();
-
- // Set the module's load address to LOAD_ADDRESS; addresses given
- // for functions and lines will be written to the Breakpad symbol
- // file as offsets from this address. Construction initializes this
- // module's load address to zero: addresses written to the symbol
- // file will be the same as they appear in the Function, Line, and
- // StackFrameEntry structures.
- //
- // Note that this member function has no effect on addresses stored
- // in the data added to this module; the Write member function
- // simply subtracts off the load address from addresses before it
- // prints them. Only the last load address given before calling
- // Write is used.
- void SetLoadAddress(Address load_address);
-
- // Add FUNCTION to the module. FUNCTION's name must not be empty.
- // This module owns all Function objects added with this function:
- // destroying the module destroys them as well.
- void AddFunction(Function *function);
-
- // Add all the functions in [BEGIN,END) to the module.
- // This module owns all Function objects added with this function:
- // destroying the module destroys them as well.
- void AddFunctions(vector<Function *>::iterator begin,
- vector<Function *>::iterator end);
-
- // Add STACK_FRAME_ENTRY to the module.
- // This module owns all StackFrameEntry objects added with this
- // function: destroying the module destroys them as well.
- void AddStackFrameEntry(StackFrameEntry *stack_frame_entry);
-
- // Add PUBLIC to the module.
- // This module owns all Extern objects added with this function:
- // destroying the module destroys them as well.
- void AddExtern(Extern *ext);
-
- // If this module has a file named NAME, return a pointer to it. If
- // it has none, then create one and return a pointer to the new
- // file. This module owns all File objects created using these
- // functions; destroying the module destroys them as well.
- File *FindFile(const string &name);
- File *FindFile(const char *name);
-
- // If this module has a file named NAME, return a pointer to it.
- // Otherwise, return NULL.
- File *FindExistingFile(const string &name);
-
- // Insert pointers to the functions added to this module at I in
- // VEC. The pointed-to Functions are still owned by this module.
- // (Since this is effectively a copy of the function list, this is
- // mostly useful for testing; other uses should probably get a more
- // appropriate interface.)
- void GetFunctions(vector<Function *> *vec, vector<Function *>::iterator i);
-
- // Insert pointers to the externs added to this module at I in
- // VEC. The pointed-to Externs are still owned by this module.
- // (Since this is effectively a copy of the extern list, this is
- // mostly useful for testing; other uses should probably get a more
- // appropriate interface.)
- void GetExterns(vector<Extern *> *vec, vector<Extern *>::iterator i);
-
- // Clear VEC and fill it with pointers to the Files added to this
- // module, sorted by name. The pointed-to Files are still owned by
- // this module. (Since this is effectively a copy of the file list,
- // this is mostly useful for testing; other uses should probably get
- // a more appropriate interface.)
- void GetFiles(vector<File *> *vec);
-
- // Clear VEC and fill it with pointers to the StackFrameEntry
- // objects that have been added to this module. (Since this is
- // effectively a copy of the stack frame entry list, this is mostly
- // useful for testing; other uses should probably get
- // a more appropriate interface.)
- void GetStackFrameEntries(vector<StackFrameEntry *> *vec) const;
-
- // If this module has a StackFrameEntry whose address range covers
- // ADDRESS, return it. Otherwise return NULL.
- StackFrameEntry* FindStackFrameEntryByAddress(Address address);
-
- // Find those files in this module that are actually referred to by
- // functions' line number data, and assign them source id numbers.
- // Set the source id numbers for all other files --- unused by the
- // source line data --- to -1. We do this before writing out the
- // symbol file, at which point we omit any unused files.
- void AssignSourceIds();
-
- // Call AssignSourceIds, and write this module to STREAM in the
- // breakpad symbol format. Return true if all goes well, or false if
- // an error occurs. This method writes out:
- // - a header based on the values given to the constructor,
- // If symbol_data is not ONLY_CFI then:
- // - the source files added via FindFile,
- // - the functions added via AddFunctions, each with its lines,
- // - all public records,
- // If symbol_data is not NO_CFI then:
- // - all CFI records.
- // Addresses in the output are all relative to the load address
- // established by SetLoadAddress.
- bool Write(std::ostream &stream, SymbolData symbol_data);
-
- string name() const { return name_; }
- string os() const { return os_; }
- string architecture() const { return architecture_; }
- string identifier() const { return id_; }
- string code_identifier() const { return code_id_; }
-
- private:
- // Report an error that has occurred writing the symbol file, using
- // errno to find the appropriate cause. Return false.
- static bool ReportError();
-
- // Write RULE_MAP to STREAM, in the form appropriate for 'STACK CFI'
- // records, without a final newline. Return true if all goes well;
- // if an error occurs, return false, and leave errno set.
- static bool WriteRuleMap(const RuleMap &rule_map, std::ostream &stream);
-
- // Module header entries.
- string name_, os_, architecture_, id_, code_id_;
-
- // The module's nominal load address. Addresses for functions and
- // lines are absolute, assuming the module is loaded at this
- // address.
- Address load_address_;
-
- // Relation for maps whose keys are strings shared with some other
- // structure.
- struct CompareStringPtrs {
- bool operator()(const string *x, const string *y) const { return *x < *y; }
- };
-
- // A map from filenames to File structures. The map's keys are
- // pointers to the Files' names.
- typedef map<const string *, File *, CompareStringPtrs> FileByNameMap;
-
- // A set containing Function structures, sorted by address.
- typedef set<Function *, FunctionCompare> FunctionSet;
-
- // A set containing Extern structures, sorted by address.
- typedef set<Extern *, ExternCompare> ExternSet;
-
- // A set containing StackFrameEntry structures, sorted by address.
- typedef set<StackFrameEntry*, StackFrameEntryCompare> StackFrameEntrySet;
-
- // The module owns all the files and functions that have been added
- // to it; destroying the module frees the Files and Functions these
- // point to.
- FileByNameMap files_; // This module's source files.
- FunctionSet functions_; // This module's functions.
-
- // The module owns all the call frame info entries that have been
- // added to it.
- StackFrameEntrySet stack_frame_entries_;
-
- // The module owns all the externs that have been added to it;
- // destroying the module frees the Externs these point to.
- ExternSet externs_;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_LINUX_MODULE_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc
deleted file mode 100644
index 3789f9ec5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/module_unittest.cc
+++ /dev/null
@@ -1,616 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// module_unittest.cc: Unit tests for google_breakpad::Module.
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
-#include <sstream>
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/module.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::Module;
-using std::stringstream;
-using std::vector;
-using testing::ContainerEq;
-
-static Module::Function *generate_duplicate_function(const string &name) {
- const Module::Address DUP_ADDRESS = 0xd35402aac7a7ad5cLL;
- const Module::Address DUP_SIZE = 0x200b26e605f99071LL;
- const Module::Address DUP_PARAMETER_SIZE = 0xf14ac4fed48c4a99LL;
-
- Module::Function *function = new Module::Function(name, DUP_ADDRESS);
- function->size = DUP_SIZE;
- function->parameter_size = DUP_PARAMETER_SIZE;
- return function;
-}
-
-#define MODULE_NAME "name with spaces"
-#define MODULE_OS "os-name"
-#define MODULE_ARCH "architecture"
-#define MODULE_ID "id-string"
-#define MODULE_CODE_ID "code-id-string"
-
-TEST(Write, Header) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n",
- contents.c_str());
-}
-
-TEST(Write, HeaderCodeId) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID, MODULE_CODE_ID);
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "INFO CODE_ID code-id-string\n",
- contents.c_str());
-}
-
-TEST(Write, OneLineFunc) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- Module::File *file = m.FindFile("file_name.cc");
- Module::Function *function = new Module::Function(
- "function_name", 0xe165bf8023b9d9abLL);
- function->size = 0x1e4bb0eb1cbf5b09LL;
- function->parameter_size = 0x772beee89114358aLL;
- Module::Line line = { 0xe165bf8023b9d9abLL, 0x1e4bb0eb1cbf5b09LL,
- file, 67519080 };
- function->lines.push_back(line);
- m.AddFunction(function);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FILE 0 file_name.cc\n"
- "FUNC e165bf8023b9d9ab 1e4bb0eb1cbf5b09 772beee89114358a"
- " function_name\n"
- "e165bf8023b9d9ab 1e4bb0eb1cbf5b09 67519080 0\n",
- contents.c_str());
-}
-
-TEST(Write, RelativeLoadAddress) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Some source files. We will expect to see them in lexicographic order.
- Module::File *file1 = m.FindFile("filename-b.cc");
- Module::File *file2 = m.FindFile("filename-a.cc");
-
- // A function.
- Module::Function *function = new Module::Function(
- "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
- function->size = 0x2922088f98d3f6fcLL;
- function->parameter_size = 0xe5e9aa008bd5f0d0LL;
-
- // Some source lines. The module should not sort these.
- Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
- file1, 41676901 };
- Module::Line line2 = { 0xdaf35bc123885c04LL, 0xcf621b8d324d0ebLL,
- file2, 67519080 };
- function->lines.push_back(line2);
- function->lines.push_back(line1);
-
- m.AddFunction(function);
-
- // Some stack information.
- Module::StackFrameEntry *entry = new Module::StackFrameEntry();
- entry->address = 0x30f9e5c83323973dULL;
- entry->size = 0x49fc9ca7c7c13dc2ULL;
- entry->initial_rules[".cfa"] = "he was a handsome man";
- entry->initial_rules["and"] = "what i want to know is";
- entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
- "do you like your blueeyed boy";
- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
- m.AddStackFrameEntry(entry);
-
- // Set the load address. Doing this after adding all the data to
- // the module must work fine.
- m.SetLoadAddress(0x2ab698b0b6407073LL);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FILE 0 filename-a.cc\n"
- "FILE 1 filename-b.cc\n"
- "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
- " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
- "b03cc3106d47eb91 cf621b8d324d0eb 67519080 0\n"
- "9410dc39a798c580 1c2be6d6c5af2611 41676901 1\n"
- "STACK CFI INIT 6434d177ce326ca 49fc9ca7c7c13dc2"
- " .cfa: he was a handsome man"
- " and: what i want to know is\n"
- "STACK CFI 6434d177ce326cb"
- " Mister: Death"
- " how: do you like your blueeyed boy\n",
- contents.c_str());
-}
-
-TEST(Write, OmitUnusedFiles) {
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Create some source files.
- Module::File *file1 = m.FindFile("filename1");
- m.FindFile("filename2"); // not used by any line
- Module::File *file3 = m.FindFile("filename3");
-
- // Create a function.
- Module::Function *function = new Module::Function(
- "function_name", 0x9b926d464f0b9384LL);
- function->size = 0x4f524a4ba795e6a6LL;
- function->parameter_size = 0xbbe8133a6641c9b7LL;
-
- // Source files that refer to some files, but not others.
- Module::Line line1 = { 0x595fa44ebacc1086LL, 0x1e1e0191b066c5b3LL,
- file1, 137850127 };
- Module::Line line2 = { 0x401ce8c8a12d25e3LL, 0x895751c41b8d2ce2LL,
- file3, 28113549 };
- function->lines.push_back(line1);
- function->lines.push_back(line2);
- m.AddFunction(function);
-
- m.AssignSourceIds();
-
- vector<Module::File *> vec;
- m.GetFiles(&vec);
- EXPECT_EQ((size_t) 3, vec.size());
- EXPECT_STREQ("filename1", vec[0]->name.c_str());
- EXPECT_NE(-1, vec[0]->source_id);
- // Expect filename2 not to be used.
- EXPECT_STREQ("filename2", vec[1]->name.c_str());
- EXPECT_EQ(-1, vec[1]->source_id);
- EXPECT_STREQ("filename3", vec[2]->name.c_str());
- EXPECT_NE(-1, vec[2]->source_id);
-
- stringstream s;
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FILE 0 filename1\n"
- "FILE 1 filename3\n"
- "FUNC 9b926d464f0b9384 4f524a4ba795e6a6 bbe8133a6641c9b7"
- " function_name\n"
- "595fa44ebacc1086 1e1e0191b066c5b3 137850127 0\n"
- "401ce8c8a12d25e3 895751c41b8d2ce2 28113549 1\n",
- contents.c_str());
-}
-
-TEST(Write, NoCFI) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Some source files. We will expect to see them in lexicographic order.
- Module::File *file1 = m.FindFile("filename.cc");
-
- // A function.
- Module::Function *function = new Module::Function(
- "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)", 0xbec774ea5dd935f3LL);
- function->size = 0x2922088f98d3f6fcLL;
- function->parameter_size = 0xe5e9aa008bd5f0d0LL;
-
- // Some source lines. The module should not sort these.
- Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
- file1, 41676901 };
- function->lines.push_back(line1);
-
- m.AddFunction(function);
-
- // Some stack information.
- Module::StackFrameEntry *entry = new Module::StackFrameEntry();
- entry->address = 0x30f9e5c83323973dULL;
- entry->size = 0x49fc9ca7c7c13dc2ULL;
- entry->initial_rules[".cfa"] = "he was a handsome man";
- entry->initial_rules["and"] = "what i want to know is";
- entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
- "do you like your blueeyed boy";
- entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
- m.AddStackFrameEntry(entry);
-
- // Set the load address. Doing this after adding all the data to
- // the module must work fine.
- m.SetLoadAddress(0x2ab698b0b6407073LL);
-
- m.Write(s, NO_CFI);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FILE 0 filename.cc\n"
- "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
- " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
- "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n",
- contents.c_str());
-}
-
-TEST(Construct, AddFunctions) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two functions.
- Module::Function *function1 = new Module::Function(
- "_without_form", 0xd35024aa7ca7da5cLL);
- function1->size = 0x200b26e605f99071LL;
- function1->parameter_size = 0xf14ac4fed48c4a99LL;
-
- Module::Function *function2 = new Module::Function(
- "_and_void", 0x2987743d0b35b13fLL);
- function2->size = 0xb369db048deb3010LL;
- function2->parameter_size = 0x938e556cb5a79988LL;
-
- // Put them in a vector.
- vector<Module::Function *> vec;
- vec.push_back(function1);
- vec.push_back(function2);
-
- m.AddFunctions(vec.begin(), vec.end());
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988"
- " _and_void\n"
- "FUNC d35024aa7ca7da5c 200b26e605f99071 f14ac4fed48c4a99"
- " _without_form\n",
- contents.c_str());
-
- // Check that m.GetFunctions returns the functions we expect.
- vec.clear();
- m.GetFunctions(&vec, vec.end());
- EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function1));
- EXPECT_TRUE(vec.end() != find(vec.begin(), vec.end(), function2));
- EXPECT_EQ((size_t) 2, vec.size());
-}
-
-TEST(Construct, AddFrames) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // First STACK CFI entry, with no initial rules or deltas.
- Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
- entry1->address = 0xddb5f41285aa7757ULL;
- entry1->size = 0x1486493370dc5073ULL;
- m.AddStackFrameEntry(entry1);
-
- // Second STACK CFI entry, with initial rules but no deltas.
- Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
- entry2->address = 0x8064f3af5e067e38ULL;
- entry2->size = 0x0de2a5ee55509407ULL;
- entry2->initial_rules[".cfa"] = "I think that I shall never see";
- entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
- entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
- m.AddStackFrameEntry(entry2);
-
- // Third STACK CFI entry, with initial rules and deltas.
- Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
- entry3->address = 0x5e8d0db0a7075c6cULL;
- entry3->size = 0x1c7edb12a7aea229ULL;
- entry3->initial_rules[".cfa"] = "Whose woods are these";
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
- "the village though";
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
- "he will not see me stopping here";
- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
- "his house is in";
- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
- "I think I know";
- m.AddStackFrameEntry(entry3);
-
- // Check that Write writes STACK CFI records properly.
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "STACK CFI INIT 5e8d0db0a7075c6c 1c7edb12a7aea229"
- " .cfa: Whose woods are these\n"
- "STACK CFI 36682fad3763ffff"
- " .cfa: I think I know"
- " stromboli: his house is in\n"
- "STACK CFI 47ceb0f63c269d7f"
- " calzone: the village though"
- " cannoli: he will not see me stopping here\n"
- "STACK CFI INIT 8064f3af5e067e38 de2a5ee55509407"
- " .cfa: I think that I shall never see"
- " cannoli: a tree whose hungry mouth is prest"
- " stromboli: a poem lovely as a tree\n"
- "STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n",
- contents.c_str());
-
- // Check that GetStackFrameEntries works.
- vector<Module::StackFrameEntry *> entries;
- m.GetStackFrameEntries(&entries);
- ASSERT_EQ(3U, entries.size());
- // Check first entry.
- EXPECT_EQ(0x5e8d0db0a7075c6cULL, entries[0]->address);
- EXPECT_EQ(0x1c7edb12a7aea229ULL, entries[0]->size);
- Module::RuleMap entry1_initial;
- entry1_initial[".cfa"] = "Whose woods are these";
- EXPECT_THAT(entries[0]->initial_rules, ContainerEq(entry1_initial));
- Module::RuleChangeMap entry1_changes;
- entry1_changes[0x36682fad3763ffffULL][".cfa"] = "I think I know";
- entry1_changes[0x36682fad3763ffffULL]["stromboli"] = "his house is in";
- entry1_changes[0x47ceb0f63c269d7fULL]["calzone"] = "the village though";
- entry1_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
- "he will not see me stopping here";
- EXPECT_THAT(entries[0]->rule_changes, ContainerEq(entry1_changes));
- // Check second entry.
- EXPECT_EQ(0x8064f3af5e067e38ULL, entries[1]->address);
- EXPECT_EQ(0x0de2a5ee55509407ULL, entries[1]->size);
- ASSERT_EQ(3U, entries[1]->initial_rules.size());
- Module::RuleMap entry2_initial;
- entry2_initial[".cfa"] = "I think that I shall never see";
- entry2_initial["stromboli"] = "a poem lovely as a tree";
- entry2_initial["cannoli"] = "a tree whose hungry mouth is prest";
- EXPECT_THAT(entries[1]->initial_rules, ContainerEq(entry2_initial));
- ASSERT_EQ(0U, entries[1]->rule_changes.size());
- // Check third entry.
- EXPECT_EQ(0xddb5f41285aa7757ULL, entries[2]->address);
- EXPECT_EQ(0x1486493370dc5073ULL, entries[2]->size);
- ASSERT_EQ(0U, entries[2]->initial_rules.size());
- ASSERT_EQ(0U, entries[2]->rule_changes.size());
-}
-
-TEST(Construct, UniqueFiles) {
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
- Module::File *file1 = m.FindFile("foo");
- Module::File *file2 = m.FindFile(string("bar"));
- Module::File *file3 = m.FindFile(string("foo"));
- Module::File *file4 = m.FindFile("bar");
- EXPECT_NE(file1, file2);
- EXPECT_EQ(file1, file3);
- EXPECT_EQ(file2, file4);
- EXPECT_EQ(file1, m.FindExistingFile("foo"));
- EXPECT_TRUE(m.FindExistingFile("baz") == NULL);
-}
-
-TEST(Construct, DuplicateFunctions) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two functions.
- Module::Function *function1 = generate_duplicate_function("_without_form");
- Module::Function *function2 = generate_duplicate_function("_without_form");
-
- m.AddFunction(function1);
- m.AddFunction(function2);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
- " _without_form\n",
- contents.c_str());
-}
-
-TEST(Construct, FunctionsWithSameAddress) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two functions.
- Module::Function *function1 = generate_duplicate_function("_without_form");
- Module::Function *function2 = generate_duplicate_function("_and_void");
-
- m.AddFunction(function1);
- m.AddFunction(function2);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
- EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
- "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
- " _and_void\n"
- "FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
- " _without_form\n",
- contents.c_str());
-}
-
-// Externs should be written out as PUBLIC records, sorted by
-// address.
-TEST(Construct, Externs) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two externs.
- Module::Extern *extern1 = new Module::Extern(0xffff);
- extern1->name = "_abc";
- Module::Extern *extern2 = new Module::Extern(0xaaaa);
- extern2->name = "_xyz";
-
- m.AddExtern(extern1);
- m.AddExtern(extern2);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
-
- EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
- MODULE_ID " " MODULE_NAME "\n"
- "PUBLIC aaaa 0 _xyz\n"
- "PUBLIC ffff 0 _abc\n",
- contents.c_str());
-}
-
-// Externs with the same address should only keep the first entry
-// added.
-TEST(Construct, DuplicateExterns) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two externs.
- Module::Extern *extern1 = new Module::Extern(0xffff);
- extern1->name = "_xyz";
- Module::Extern *extern2 = new Module::Extern(0xffff);
- extern2->name = "_abc";
-
- m.AddExtern(extern1);
- m.AddExtern(extern2);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
-
- EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
- MODULE_ID " " MODULE_NAME "\n"
- "PUBLIC ffff 0 _xyz\n",
- contents.c_str());
-}
-
-// If there exists an extern and a function at the same address, only write
-// out the FUNC entry.
-TEST(Construct, FunctionsAndExternsWithSameAddress) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // Two externs.
- Module::Extern* extern1 = new Module::Extern(0xabc0);
- extern1->name = "abc";
- Module::Extern* extern2 = new Module::Extern(0xfff0);
- extern2->name = "xyz";
-
- m.AddExtern(extern1);
- m.AddExtern(extern2);
-
- Module::Function* function = new Module::Function("_xyz", 0xfff0);
- function->size = 0x10;
- function->parameter_size = 0;
- m.AddFunction(function);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
-
- EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
- MODULE_ID " " MODULE_NAME "\n"
- "FUNC fff0 10 0 _xyz\n"
- "PUBLIC abc0 0 abc\n",
- contents.c_str());
-}
-
-// If there exists an extern and a function at the same address, only write
-// out the FUNC entry. For ARM THUMB, the extern that comes from the ELF
-// symbol section has bit 0 set.
-TEST(Construct, FunctionsAndThumbExternsWithSameAddress) {
- stringstream s;
- Module m(MODULE_NAME, MODULE_OS, "arm", MODULE_ID);
-
- // Two THUMB externs.
- Module::Extern* thumb_extern1 = new Module::Extern(0xabc1);
- thumb_extern1->name = "thumb_abc";
- Module::Extern* thumb_extern2 = new Module::Extern(0xfff1);
- thumb_extern2->name = "thumb_xyz";
-
- Module::Extern* arm_extern1 = new Module::Extern(0xcc00);
- arm_extern1->name = "arm_func";
-
- m.AddExtern(thumb_extern1);
- m.AddExtern(thumb_extern2);
- m.AddExtern(arm_extern1);
-
- // The corresponding function from the DWARF debug data have the actual
- // address.
- Module::Function* function = new Module::Function("_thumb_xyz", 0xfff0);
- function->size = 0x10;
- function->parameter_size = 0;
- m.AddFunction(function);
-
- m.Write(s, ALL_SYMBOL_DATA);
- string contents = s.str();
-
- EXPECT_STREQ("MODULE " MODULE_OS " arm "
- MODULE_ID " " MODULE_NAME "\n"
- "FUNC fff0 10 0 _thumb_xyz\n"
- "PUBLIC abc1 0 thumb_abc\n"
- "PUBLIC cc00 0 arm_func\n",
- contents.c_str());
-}
-
-TEST(Lookup, StackFrameEntries) {
- Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
-
- // First STACK CFI entry, with no initial rules or deltas.
- Module::StackFrameEntry *entry1 = new Module::StackFrameEntry();
- entry1->address = 0x2000;
- entry1->size = 0x900;
- m.AddStackFrameEntry(entry1);
-
- // Second STACK CFI entry, with initial rules but no deltas.
- Module::StackFrameEntry *entry2 = new Module::StackFrameEntry();
- entry2->address = 0x3000;
- entry2->size = 0x900;
- entry2->initial_rules[".cfa"] = "I think that I shall never see";
- entry2->initial_rules["stromboli"] = "a poem lovely as a tree";
- entry2->initial_rules["cannoli"] = "a tree whose hungry mouth is prest";
- m.AddStackFrameEntry(entry2);
-
- // Third STACK CFI entry, with initial rules and deltas.
- Module::StackFrameEntry *entry3 = new Module::StackFrameEntry();
- entry3->address = 0x1000;
- entry3->size = 0x900;
- entry3->initial_rules[".cfa"] = "Whose woods are these";
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["calzone"] =
- "the village though";
- entry3->rule_changes[0x47ceb0f63c269d7fULL]["cannoli"] =
- "he will not see me stopping here";
- entry3->rule_changes[0x36682fad3763ffffULL]["stromboli"] =
- "his house is in";
- entry3->rule_changes[0x36682fad3763ffffULL][".cfa"] =
- "I think I know";
- m.AddStackFrameEntry(entry3);
-
- Module::StackFrameEntry* s = m.FindStackFrameEntryByAddress(0x1000);
- EXPECT_EQ(entry3, s);
- s = m.FindStackFrameEntryByAddress(0x18FF);
- EXPECT_EQ(entry3, s);
-
- s = m.FindStackFrameEntryByAddress(0x1900);
- EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
- s = m.FindStackFrameEntryByAddress(0x1A00);
- EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
-
- s = m.FindStackFrameEntryByAddress(0x2000);
- EXPECT_EQ(entry1, s);
- s = m.FindStackFrameEntryByAddress(0x28FF);
- EXPECT_EQ(entry1, s);
-
- s = m.FindStackFrameEntryByAddress(0x3000);
- EXPECT_EQ(entry2, s);
- s = m.FindStackFrameEntryByAddress(0x38FF);
- EXPECT_EQ(entry2, s);
-
- s = m.FindStackFrameEntryByAddress(0x3900);
- EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
- s = m.FindStackFrameEntryByAddress(0x3A00);
- EXPECT_EQ((Module::StackFrameEntry*)NULL, s);
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/moz.build b/toolkit/crashreporter/google-breakpad/src/common/moz.build
deleted file mode 100644
index 7bb6e9b6d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/moz.build
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-if CONFIG['OS_ARCH'] in ('Darwin', 'Linux'):
- DIRS += ['dwarf']
-
-UNIFIED_SOURCES += [
- 'convert_UTF.c',
- 'string_conversion.cc',
-]
-
-if CONFIG['OS_ARCH'] != 'WINNT':
- UNIFIED_SOURCES += [
- 'md5.cc',
- ]
-
-if CONFIG['OS_ARCH'] == 'Linux':
- HOST_DEFINES['HAVE_A_OUT_H'] = True
-elif CONFIG['OS_ARCH'] == 'Darwin':
- HOST_DEFINES['HAVE_MACH_O_NLIST_H'] = True
- HOST_SOURCES += [
- 'stabs_reader.cc',
- 'stabs_to_module.cc',
- ]
- if CONFIG['HOST_OS_ARCH'] != 'Darwin':
- HOST_CXXFLAGS += [
- '-I%s/toolkit/crashreporter/google-breakpad/src/third_party/mac_headers/' % TOPSRCDIR,
- ]
-
-if CONFIG['OS_ARCH'] != 'WINNT':
- HOST_SOURCES += [
- 'arm_ex_reader.cc',
- 'arm_ex_to_module.cc',
- 'convert_UTF.c',
- 'dwarf_cfi_to_module.cc',
- 'dwarf_cu_to_module.cc',
- 'dwarf_line_to_module.cc',
- 'language.cc',
- 'md5.cc',
- 'module.cc',
- 'string_conversion.cc',
- ]
- if CONFIG['OS_ARCH'] == 'Darwin':
- HOST_CXXFLAGS += [
- '-stdlib=libc++',
- ]
- HOST_CXXFLAGS += [
- '-O2',
- '-g',
- ]
- HostLibrary('host_breakpad_common_s')
-
-if CONFIG['OS_TARGET'] == 'Android':
- # We don't support unifying assembly files.
- SOURCES += [
- 'android/breakpad_getcontext.S',
- ]
- LOCAL_INCLUDES += [
- '/toolkit/crashreporter/google-breakpad/src/common/android/include',
- ]
-
-Library('breakpad_common_s')
-
-# We allow warnings for third-party code that can be updated from upstream.
-ALLOW_COMPILER_WARNINGS = True
-
-FINAL_LIBRARY = 'xul'
-
-include('/toolkit/crashreporter/crashreporter.mozbuild')
diff --git a/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h b/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h
deleted file mode 100644
index d137c1868..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/scoped_ptr.h
+++ /dev/null
@@ -1,404 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Scopers help you manage ownership of a pointer, helping you easily manage the
-// a pointer within a scope, and automatically destroying the pointer at the
-// end of a scope. There are two main classes you will use, which correspond
-// to the operators new/delete and new[]/delete[].
-//
-// Example usage (scoped_ptr):
-// {
-// scoped_ptr<Foo> foo(new Foo("wee"));
-// } // foo goes out of scope, releasing the pointer with it.
-//
-// {
-// scoped_ptr<Foo> foo; // No pointer managed.
-// foo.reset(new Foo("wee")); // Now a pointer is managed.
-// foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
-// foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
-// foo->Method(); // Foo::Method() called.
-// foo.get()->Method(); // Foo::Method() called.
-// SomeFunc(foo.release()); // SomeFunc takes ownership, foo no longer
-// // manages a pointer.
-// foo.reset(new Foo("wee4")); // foo manages a pointer again.
-// foo.reset(); // Foo("wee4") destroyed, foo no longer
-// // manages a pointer.
-// } // foo wasn't managing a pointer, so nothing was destroyed.
-//
-// Example usage (scoped_array):
-// {
-// scoped_array<Foo> foo(new Foo[100]);
-// foo.get()->Method(); // Foo::Method on the 0th element.
-// foo[10].Method(); // Foo::Method on the 10th element.
-// }
-
-#ifndef COMMON_SCOPED_PTR_H_
-#define COMMON_SCOPED_PTR_H_
-
-// This is an implementation designed to match the anticipated future TR2
-// implementation of the scoped_ptr class, and its closely-related brethren,
-// scoped_array, scoped_ptr_malloc.
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-namespace google_breakpad {
-
-// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
-// automatically deletes the pointer it holds (if any).
-// That is, scoped_ptr<T> owns the T object that it points to.
-// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
-// Also like T*, scoped_ptr<T> is thread-compatible, and once you
-// dereference it, you get the threadsafety guarantees of T.
-//
-// The size of a scoped_ptr is small:
-// sizeof(scoped_ptr<C>) == sizeof(C*)
-template <class C>
-class scoped_ptr {
- public:
-
- // The element type
- typedef C element_type;
-
- // Constructor. Defaults to initializing with NULL.
- // There is no way to create an uninitialized scoped_ptr.
- // The input parameter must be allocated with new.
- explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
-
- // Destructor. If there is a C object, delete it.
- // We don't need to test ptr_ == NULL because C++ does that for us.
- ~scoped_ptr() {
- enum { type_must_be_complete = sizeof(C) };
- delete ptr_;
- }
-
- // Reset. Deletes the current owned object, if any.
- // Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
- void reset(C* p = NULL) {
- if (p != ptr_) {
- enum { type_must_be_complete = sizeof(C) };
- delete ptr_;
- ptr_ = p;
- }
- }
-
- // Accessors to get the owned object.
- // operator* and operator-> will assert() if there is no current object.
- C& operator*() const {
- assert(ptr_ != NULL);
- return *ptr_;
- }
- C* operator->() const {
- assert(ptr_ != NULL);
- return ptr_;
- }
- C* get() const { return ptr_; }
-
- // Comparison operators.
- // These return whether two scoped_ptr refer to the same object, not just to
- // two different but equal objects.
- bool operator==(C* p) const { return ptr_ == p; }
- bool operator!=(C* p) const { return ptr_ != p; }
-
- // Swap two scoped pointers.
- void swap(scoped_ptr& p2) {
- C* tmp = ptr_;
- ptr_ = p2.ptr_;
- p2.ptr_ = tmp;
- }
-
- // Release a pointer.
- // The return value is the current pointer held by this object.
- // If this object holds a NULL pointer, the return value is NULL.
- // After this operation, this object will hold a NULL pointer,
- // and will not own the object any more.
- C* release() {
- C* retVal = ptr_;
- ptr_ = NULL;
- return retVal;
- }
-
- private:
- C* ptr_;
-
- // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
- // make sense, and if C2 == C, it still doesn't make sense because you should
- // never have the same object owned by two different scoped_ptrs.
- template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
- template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
-
- // Disallow evil constructors
- scoped_ptr(const scoped_ptr&);
- void operator=(const scoped_ptr&);
-};
-
-// Free functions
-template <class C>
-void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
- p1.swap(p2);
-}
-
-template <class C>
-bool operator==(C* p1, const scoped_ptr<C>& p2) {
- return p1 == p2.get();
-}
-
-template <class C>
-bool operator!=(C* p1, const scoped_ptr<C>& p2) {
- return p1 != p2.get();
-}
-
-// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
-// with new [] and the destructor deletes objects with delete [].
-//
-// As with scoped_ptr<C>, a scoped_array<C> either points to an object
-// or is NULL. A scoped_array<C> owns the object that it points to.
-// scoped_array<T> is thread-compatible, and once you index into it,
-// the returned objects have only the threadsafety guarantees of T.
-//
-// Size: sizeof(scoped_array<C>) == sizeof(C*)
-template <class C>
-class scoped_array {
- public:
-
- // The element type
- typedef C element_type;
-
- // Constructor. Defaults to intializing with NULL.
- // There is no way to create an uninitialized scoped_array.
- // The input parameter must be allocated with new [].
- explicit scoped_array(C* p = NULL) : array_(p) { }
-
- // Destructor. If there is a C object, delete it.
- // We don't need to test ptr_ == NULL because C++ does that for us.
- ~scoped_array() {
- enum { type_must_be_complete = sizeof(C) };
- delete[] array_;
- }
-
- // Reset. Deletes the current owned object, if any.
- // Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
- void reset(C* p = NULL) {
- if (p != array_) {
- enum { type_must_be_complete = sizeof(C) };
- delete[] array_;
- array_ = p;
- }
- }
-
- // Get one element of the current object.
- // Will assert() if there is no current object, or index i is negative.
- C& operator[](ptrdiff_t i) const {
- assert(i >= 0);
- assert(array_ != NULL);
- return array_[i];
- }
-
- // Get a pointer to the zeroth element of the current object.
- // If there is no current object, return NULL.
- C* get() const {
- return array_;
- }
-
- // Comparison operators.
- // These return whether two scoped_array refer to the same object, not just to
- // two different but equal objects.
- bool operator==(C* p) const { return array_ == p; }
- bool operator!=(C* p) const { return array_ != p; }
-
- // Swap two scoped arrays.
- void swap(scoped_array& p2) {
- C* tmp = array_;
- array_ = p2.array_;
- p2.array_ = tmp;
- }
-
- // Release an array.
- // The return value is the current pointer held by this object.
- // If this object holds a NULL pointer, the return value is NULL.
- // After this operation, this object will hold a NULL pointer,
- // and will not own the object any more.
- C* release() {
- C* retVal = array_;
- array_ = NULL;
- return retVal;
- }
-
- private:
- C* array_;
-
- // Forbid comparison of different scoped_array types.
- template <class C2> bool operator==(scoped_array<C2> const& p2) const;
- template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
-
- // Disallow evil constructors
- scoped_array(const scoped_array&);
- void operator=(const scoped_array&);
-};
-
-// Free functions
-template <class C>
-void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
- p1.swap(p2);
-}
-
-template <class C>
-bool operator==(C* p1, const scoped_array<C>& p2) {
- return p1 == p2.get();
-}
-
-template <class C>
-bool operator!=(C* p1, const scoped_array<C>& p2) {
- return p1 != p2.get();
-}
-
-// This class wraps the c library function free() in a class that can be
-// passed as a template argument to scoped_ptr_malloc below.
-class ScopedPtrMallocFree {
- public:
- inline void operator()(void* x) const {
- free(x);
- }
-};
-
-// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
-// second template argument, the functor used to free the object.
-
-template<class C, class FreeProc = ScopedPtrMallocFree>
-class scoped_ptr_malloc {
- public:
-
- // The element type
- typedef C element_type;
-
- // Constructor. Defaults to initializing with NULL.
- // There is no way to create an uninitialized scoped_ptr.
- // The input parameter must be allocated with an allocator that matches the
- // Free functor. For the default Free functor, this is malloc, calloc, or
- // realloc.
- explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
-
- // Destructor. If there is a C object, call the Free functor.
- ~scoped_ptr_malloc() {
- reset();
- }
-
- // Reset. Calls the Free functor on the current owned object, if any.
- // Then takes ownership of a new object, if given.
- // this->reset(this->get()) works.
- void reset(C* p = NULL) {
- if (ptr_ != p) {
- FreeProc free_proc;
- free_proc(ptr_);
- ptr_ = p;
- }
- }
-
- // Get the current object.
- // operator* and operator-> will cause an assert() failure if there is
- // no current object.
- C& operator*() const {
- assert(ptr_ != NULL);
- return *ptr_;
- }
-
- C* operator->() const {
- assert(ptr_ != NULL);
- return ptr_;
- }
-
- C* get() const {
- return ptr_;
- }
-
- // Comparison operators.
- // These return whether a scoped_ptr_malloc and a plain pointer refer
- // to the same object, not just to two different but equal objects.
- // For compatibility with the boost-derived implementation, these
- // take non-const arguments.
- bool operator==(C* p) const {
- return ptr_ == p;
- }
-
- bool operator!=(C* p) const {
- return ptr_ != p;
- }
-
- // Swap two scoped pointers.
- void swap(scoped_ptr_malloc & b) {
- C* tmp = b.ptr_;
- b.ptr_ = ptr_;
- ptr_ = tmp;
- }
-
- // Release a pointer.
- // The return value is the current pointer held by this object.
- // If this object holds a NULL pointer, the return value is NULL.
- // After this operation, this object will hold a NULL pointer,
- // and will not own the object any more.
- C* release() {
- C* tmp = ptr_;
- ptr_ = NULL;
- return tmp;
- }
-
- private:
- C* ptr_;
-
- // no reason to use these: each scoped_ptr_malloc should have its own object
- template <class C2, class GP>
- bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
- template <class C2, class GP>
- bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
-
- // Disallow evil constructors
- scoped_ptr_malloc(const scoped_ptr_malloc&);
- void operator=(const scoped_ptr_malloc&);
-};
-
-template<class C, class FP> inline
-void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
- a.swap(b);
-}
-
-template<class C, class FP> inline
-bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
- return p == b.get();
-}
-
-template<class C, class FP> inline
-bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
- return p != b.get();
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_SCOPED_PTR_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.cc b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.cc
deleted file mode 100644
index e0a74ceeb..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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 "common/simple_string_dictionary.h"
-
-namespace google_breakpad {
-
-namespace {
-
-// In C++98 (ISO 14882), section 9.5.1 says that a union cannot have a member
-// with a non-trivial ctor, copy ctor, dtor, or assignment operator. Use this
-// property to ensure that Entry remains POD.
-union Compile_Assert {
- NonAllocatingMap<1, 1, 1>::Entry Compile_Assert__entry_must_be_pod;
-};
-
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h
deleted file mode 100644
index d2ab17fda..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary.h
+++ /dev/null
@@ -1,260 +0,0 @@
-// 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.
-
-#ifndef COMMON_SIMPLE_STRING_DICTIONARY_H_
-#define COMMON_SIMPLE_STRING_DICTIONARY_H_
-
-#include <assert.h>
-#include <string.h>
-
-#include "common/basictypes.h"
-
-namespace google_breakpad {
-
-// Opaque type for the serialized representation of a NonAllocatingMap. One is
-// created in NonAllocatingMap::Serialize and can be deserialized using one of
-// the constructors.
-struct SerializedNonAllocatingMap;
-
-// NonAllocatingMap is an implementation of a map/dictionary collection that
-// uses a fixed amount of storage, so that it does not perform any dynamic
-// allocations for its operations.
-//
-// The actual map storage (the Entry) is guaranteed to be POD, so that it can
-// be transmitted over various IPC mechanisms.
-//
-// The template parameters control the amount of storage used for the key,
-// value, and map. The KeySize and ValueSize are measured in bytes, not glyphs,
-// and includes space for a \0 byte. This gives space for KeySize-1 and
-// ValueSize-1 characters in an entry. NumEntries is the total number of
-// entries that will fit in the map.
-template <size_t KeySize, size_t ValueSize, size_t NumEntries>
-class NonAllocatingMap {
- public:
- // Constant and publicly accessible versions of the template parameters.
- static const size_t key_size = KeySize;
- static const size_t value_size = ValueSize;
- static const size_t num_entries = NumEntries;
-
- // An Entry object is a single entry in the map. If the key is a 0-length
- // NUL-terminated string, the entry is empty.
- struct Entry {
- char key[KeySize];
- char value[ValueSize];
-
- bool is_active() const {
- return key[0] != '\0';
- }
- };
-
- // An Iterator can be used to iterate over all the active entries in a
- // NonAllocatingMap.
- class Iterator {
- public:
- explicit Iterator(const NonAllocatingMap& map)
- : map_(map),
- current_(0) {
- }
-
- // Returns the next entry in the map, or NULL if at the end of the
- // collection.
- const Entry* Next() {
- while (current_ < map_.num_entries) {
- const Entry* entry = &map_.entries_[current_++];
- if (entry->is_active()) {
- return entry;
- }
- }
- return NULL;
- }
-
- private:
- const NonAllocatingMap& map_;
- size_t current_;
-
- DISALLOW_COPY_AND_ASSIGN(Iterator);
- };
-
- NonAllocatingMap() : entries_() {
- }
-
- NonAllocatingMap(const NonAllocatingMap& other) {
- *this = other;
- }
-
- NonAllocatingMap& operator=(const NonAllocatingMap& other) {
- assert(other.key_size == key_size);
- assert(other.value_size == value_size);
- assert(other.num_entries == num_entries);
- if (other.key_size == key_size && other.value_size == value_size &&
- other.num_entries == num_entries) {
- memcpy(entries_, other.entries_, sizeof(entries_));
- }
- return *this;
- }
-
- // Constructs a map from its serialized form. |map| should be the out
- // parameter from Serialize() and |size| should be its return value.
- NonAllocatingMap(const SerializedNonAllocatingMap* map, size_t size) {
- assert(size == sizeof(entries_));
- if (size == sizeof(entries_)) {
- memcpy(entries_, map, size);
- }
- }
-
- // Returns the number of active key/value pairs. The upper limit for this
- // is NumEntries.
- size_t GetCount() const {
- size_t count = 0;
- for (size_t i = 0; i < num_entries; ++i) {
- if (entries_[i].is_active()) {
- ++count;
- }
- }
- return count;
- }
-
- // Given |key|, returns its corresponding |value|. |key| must not be NULL. If
- // the key is not found, NULL is returned.
- const char* GetValueForKey(const char* key) const {
- assert(key);
- if (!key)
- return NULL;
-
- const Entry* entry = GetConstEntryForKey(key);
- if (!entry)
- return NULL;
-
- return entry->value;
- }
-
- // Stores |value| into |key|, replacing the existing value if |key| is
- // already present. |key| must not be NULL. If |value| is NULL, the key is
- // removed from the map. If there is no more space in the map, then the
- // operation silently fails.
- void SetKeyValue(const char* key, const char* value) {
- if (!value) {
- RemoveKey(key);
- return;
- }
-
- assert(key);
- if (!key)
- return;
-
- // Key must not be an empty string.
- assert(key[0] != '\0');
- if (key[0] == '\0')
- return;
-
- Entry* entry = GetEntryForKey(key);
-
- // If it does not yet exist, attempt to insert it.
- if (!entry) {
- for (size_t i = 0; i < num_entries; ++i) {
- if (!entries_[i].is_active()) {
- entry = &entries_[i];
-
- strncpy(entry->key, key, key_size);
- entry->key[key_size - 1] = '\0';
-
- break;
- }
- }
- }
-
- // If the map is out of space, entry will be NULL.
- if (!entry)
- return;
-
-#ifndef NDEBUG
- // Sanity check that the key only appears once.
- int count = 0;
- for (size_t i = 0; i < num_entries; ++i) {
- if (strncmp(entries_[i].key, key, key_size) == 0)
- ++count;
- }
- assert(count == 1);
-#endif
-
- strncpy(entry->value, value, value_size);
- entry->value[value_size - 1] = '\0';
- }
-
- // Given |key|, removes any associated value. |key| must not be NULL. If
- // the key is not found, this is a noop.
- void RemoveKey(const char* key) {
- assert(key);
- if (!key)
- return;
-
- Entry* entry = GetEntryForKey(key);
- if (entry) {
- entry->key[0] = '\0';
- entry->value[0] = '\0';
- }
-
-#ifndef NDEBUG
- assert(GetEntryForKey(key) == NULL);
-#endif
- }
-
- // Places a serialized version of the map into |map| and returns the size.
- // Both of these should be passed to the deserializing constructor. Note that
- // the serialized |map| is scoped to the lifetime of the non-serialized
- // instance of this class. The |map| can be copied across IPC boundaries.
- size_t Serialize(const SerializedNonAllocatingMap** map) const {
- *map = reinterpret_cast<const SerializedNonAllocatingMap*>(entries_);
- return sizeof(entries_);
- }
-
- private:
- const Entry* GetConstEntryForKey(const char* key) const {
- for (size_t i = 0; i < num_entries; ++i) {
- if (strncmp(key, entries_[i].key, key_size) == 0) {
- return &entries_[i];
- }
- }
- return NULL;
- }
-
- Entry* GetEntryForKey(const char* key) {
- return const_cast<Entry*>(GetConstEntryForKey(key));
- }
-
- Entry entries_[NumEntries];
-};
-
-// For historical reasons this specialized version is available with the same
-// size factors as a previous implementation.
-typedef NonAllocatingMap<256, 256, 64> SimpleStringDictionary;
-
-} // namespace google_breakpad
-
-#endif // COMMON_SIMPLE_STRING_DICTIONARY_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc
deleted file mode 100644
index 34f4b9ef5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/simple_string_dictionary_unittest.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-// 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.
-
-#include "breakpad_googletest_includes.h"
-#include "common/simple_string_dictionary.h"
-
-namespace google_breakpad {
-
-TEST(NonAllocatingMapTest, Entry) {
- typedef NonAllocatingMap<5, 9, 15> TestMap;
- TestMap map;
-
- const TestMap::Entry* entry = TestMap::Iterator(map).Next();
- EXPECT_FALSE(entry);
-
- // Try setting a key/value and then verify.
- map.SetKeyValue("key1", "value1");
- entry = TestMap::Iterator(map).Next();
- ASSERT_TRUE(entry);
- EXPECT_STREQ(entry->key, "key1");
- EXPECT_STREQ(entry->value, "value1");
-
- // Try setting a new value.
- map.SetKeyValue("key1", "value3");
- EXPECT_STREQ(entry->value, "value3");
-
- // Make sure the key didn't change.
- EXPECT_STREQ(entry->key, "key1");
-
- // Clear the entry and verify the key and value are empty strings.
- map.RemoveKey("key1");
- EXPECT_FALSE(entry->is_active());
- EXPECT_EQ(strlen(entry->key), 0u);
- EXPECT_EQ(strlen(entry->value), 0u);
-}
-
-TEST(NonAllocatingMapTest, SimpleStringDictionary) {
- // Make a new dictionary
- SimpleStringDictionary dict;
-
- // Set three distinct values on three keys
- dict.SetKeyValue("key1", "value1");
- dict.SetKeyValue("key2", "value2");
- dict.SetKeyValue("key3", "value3");
-
- EXPECT_NE(dict.GetValueForKey("key1"), "value1");
- EXPECT_NE(dict.GetValueForKey("key2"), "value2");
- EXPECT_NE(dict.GetValueForKey("key3"), "value3");
- EXPECT_EQ(dict.GetCount(), 3u);
- // try an unknown key
- EXPECT_FALSE(dict.GetValueForKey("key4"));
-
- // Remove a key
- dict.RemoveKey("key3");
-
- // Now make sure it's not there anymore
- EXPECT_FALSE(dict.GetValueForKey("key3"));
-
- // Remove by setting value to NULL
- dict.SetKeyValue("key2", NULL);
-
- // Now make sure it's not there anymore
- EXPECT_FALSE(dict.GetValueForKey("key2"));
-}
-
-TEST(NonAllocatingMapTest, CopyAndAssign) {
- NonAllocatingMap<10, 10, 10> map;
- map.SetKeyValue("one", "a");
- map.SetKeyValue("two", "b");
- map.SetKeyValue("three", "c");
- map.RemoveKey("two");
- EXPECT_EQ(2u, map.GetCount());
-
- // Test copy.
- NonAllocatingMap<10, 10, 10> map_copy(map);
- EXPECT_EQ(2u, map_copy.GetCount());
- EXPECT_STREQ("a", map_copy.GetValueForKey("one"));
- EXPECT_STREQ("c", map_copy.GetValueForKey("three"));
- map_copy.SetKeyValue("four", "d");
- EXPECT_STREQ("d", map_copy.GetValueForKey("four"));
- EXPECT_FALSE(map.GetValueForKey("four"));
-
- // Test assign.
- NonAllocatingMap<10, 10, 10> map_assign;
- map_assign = map;
- EXPECT_EQ(2u, map_assign.GetCount());
- EXPECT_STREQ("a", map_assign.GetValueForKey("one"));
- EXPECT_STREQ("c", map_assign.GetValueForKey("three"));
- map_assign.SetKeyValue("four", "d");
- EXPECT_STREQ("d", map_assign.GetValueForKey("four"));
- EXPECT_FALSE(map.GetValueForKey("four"));
-
- map.RemoveKey("one");
- EXPECT_FALSE(map.GetValueForKey("one"));
- EXPECT_STREQ("a", map_copy.GetValueForKey("one"));
- EXPECT_STREQ("a", map_assign.GetValueForKey("one"));
-}
-
-// Add a bunch of values to the dictionary, remove some entries in the middle,
-// and then add more.
-TEST(NonAllocatingMapTest, Iterator) {
- SimpleStringDictionary* dict = new SimpleStringDictionary();
- ASSERT_TRUE(dict);
-
- char key[SimpleStringDictionary::key_size];
- char value[SimpleStringDictionary::value_size];
-
- const int kDictionaryCapacity = SimpleStringDictionary::num_entries;
- const int kPartitionIndex = kDictionaryCapacity - 5;
-
- // We assume at least this size in the tests below
- ASSERT_GE(kDictionaryCapacity, 64);
-
- // We'll keep track of the number of key/value pairs we think should
- // be in the dictionary
- int expectedDictionarySize = 0;
-
- // Set a bunch of key/value pairs like key0/value0, key1/value1, ...
- for (int i = 0; i < kPartitionIndex; ++i) {
- sprintf(key, "key%d", i);
- sprintf(value, "value%d", i);
- dict->SetKeyValue(key, value);
- }
- expectedDictionarySize = kPartitionIndex;
-
- // set a couple of the keys twice (with the same value) - should be nop
- dict->SetKeyValue("key2", "value2");
- dict->SetKeyValue("key4", "value4");
- dict->SetKeyValue("key15", "value15");
-
- // Remove some random elements in the middle
- dict->RemoveKey("key7");
- dict->RemoveKey("key18");
- dict->RemoveKey("key23");
- dict->RemoveKey("key31");
- expectedDictionarySize -= 4; // we just removed four key/value pairs
-
- // Set some more key/value pairs like key59/value59, key60/value60, ...
- for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) {
- sprintf(key, "key%d", i);
- sprintf(value, "value%d", i);
- dict->SetKeyValue(key, value);
- }
- expectedDictionarySize += kDictionaryCapacity - kPartitionIndex;
-
- // Now create an iterator on the dictionary
- SimpleStringDictionary::Iterator iter(*dict);
-
- // We then verify that it iterates through exactly the number of
- // key/value pairs we expect, and that they match one-for-one with what we
- // would expect. The ordering of the iteration does not matter...
-
- // used to keep track of number of occurrences found for key/value pairs
- int count[kDictionaryCapacity];
- memset(count, 0, sizeof(count));
-
- int totalCount = 0;
-
- const SimpleStringDictionary::Entry* entry;
- while ((entry = iter.Next())) {
- totalCount++;
-
- // Extract keyNumber from a string of the form key<keyNumber>
- int keyNumber;
- sscanf(entry->key, "key%d", &keyNumber);
-
- // Extract valueNumber from a string of the form value<valueNumber>
- int valueNumber;
- sscanf(entry->value, "value%d", &valueNumber);
-
- // The value number should equal the key number since that's how we set them
- EXPECT_EQ(keyNumber, valueNumber);
-
- // Key and value numbers should be in proper range:
- // 0 <= keyNumber < kDictionaryCapacity
- bool isKeyInGoodRange =
- (keyNumber >= 0 && keyNumber < kDictionaryCapacity);
- bool isValueInGoodRange =
- (valueNumber >= 0 && valueNumber < kDictionaryCapacity);
- EXPECT_TRUE(isKeyInGoodRange);
- EXPECT_TRUE(isValueInGoodRange);
-
- if (isKeyInGoodRange && isValueInGoodRange) {
- ++count[keyNumber];
- }
- }
-
- // Make sure each of the key/value pairs showed up exactly one time, except
- // for the ones which we removed.
- for (size_t i = 0; i < kDictionaryCapacity; ++i) {
- // Skip over key7, key18, key23, and key31, since we removed them
- if (!(i == 7 || i == 18 || i == 23 || i == 31)) {
- EXPECT_EQ(count[i], 1);
- }
- }
-
- // Make sure the number of iterations matches the expected dictionary size.
- EXPECT_EQ(totalCount, expectedDictionarySize);
-}
-
-
-TEST(NonAllocatingMapTest, AddRemove) {
- NonAllocatingMap<5, 7, 6> map;
- map.SetKeyValue("rob", "ert");
- map.SetKeyValue("mike", "pink");
- map.SetKeyValue("mark", "allays");
-
- EXPECT_EQ(3u, map.GetCount());
- EXPECT_STREQ("ert", map.GetValueForKey("rob"));
- EXPECT_STREQ("pink", map.GetValueForKey("mike"));
- EXPECT_STREQ("allays", map.GetValueForKey("mark"));
-
- map.RemoveKey("mike");
-
- EXPECT_EQ(2u, map.GetCount());
- EXPECT_FALSE(map.GetValueForKey("mike"));
-
- map.SetKeyValue("mark", "mal");
- EXPECT_EQ(2u, map.GetCount());
- EXPECT_STREQ("mal", map.GetValueForKey("mark"));
-
- map.RemoveKey("mark");
- EXPECT_EQ(1u, map.GetCount());
- EXPECT_FALSE(map.GetValueForKey("mark"));
-}
-
-TEST(NonAllocatingMapTest, Serialize) {
- typedef NonAllocatingMap<4, 5, 7> TestMap;
- TestMap map;
- map.SetKeyValue("one", "abc");
- map.SetKeyValue("two", "def");
- map.SetKeyValue("tre", "hig");
-
- EXPECT_STREQ("abc", map.GetValueForKey("one"));
- EXPECT_STREQ("def", map.GetValueForKey("two"));
- EXPECT_STREQ("hig", map.GetValueForKey("tre"));
-
- const SerializedNonAllocatingMap* serialized;
- size_t size = map.Serialize(&serialized);
-
- SerializedNonAllocatingMap* serialized_copy =
- reinterpret_cast<SerializedNonAllocatingMap*>(malloc(size));
- ASSERT_TRUE(serialized_copy);
- memcpy(serialized_copy, serialized, size);
-
- TestMap deserialized(serialized_copy, size);
- free(serialized_copy);
-
- EXPECT_EQ(3u, deserialized.GetCount());
- EXPECT_STREQ("abc", deserialized.GetValueForKey("one"));
- EXPECT_STREQ("def", deserialized.GetValueForKey("two"));
- EXPECT_STREQ("hig", deserialized.GetValueForKey("tre"));
-}
-
-// Running out of space shouldn't crash.
-TEST(NonAllocatingMapTest, OutOfSpace) {
- NonAllocatingMap<3, 2, 2> map;
- map.SetKeyValue("a", "1");
- map.SetKeyValue("b", "2");
- map.SetKeyValue("c", "3");
- EXPECT_EQ(2u, map.GetCount());
- EXPECT_FALSE(map.GetValueForKey("c"));
-}
-
-#ifndef NDEBUG
-
-TEST(NonAllocatingMapTest, NullKey) {
- NonAllocatingMap<4, 6, 6> map;
- ASSERT_DEATH(map.SetKeyValue(NULL, "hello"), "");
-
- map.SetKeyValue("hi", "there");
- ASSERT_DEATH(map.GetValueForKey(NULL), "");
- EXPECT_STREQ("there", map.GetValueForKey("hi"));
-
- ASSERT_DEATH(map.GetValueForKey(NULL), "");
- map.RemoveKey("hi");
- EXPECT_EQ(0u, map.GetCount());
-}
-
-#endif // !NDEBUG
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc
deleted file mode 100644
index 168d0b287..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.cc
+++ /dev/null
@@ -1,681 +0,0 @@
-// 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.
-
-// Author: Alfred Peng
-
-#include <demangle.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <link.h>
-#include <sys/mman.h>
-#include <stab.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <functional>
-#include <map>
-#include <vector>
-
-#include "common/scoped_ptr.h"
-#include "common/solaris/dump_symbols.h"
-#include "common/solaris/file_id.h"
-#include "common/solaris/guid_creator.h"
-
-// This namespace contains helper functions.
-namespace {
-
-using std::make_pair;
-
-#if defined(_LP64)
-typedef Elf64_Sym Elf_Sym;
-#else
-typedef Elf32_Sym Elf_Sym;
-#endif
-
-// Symbol table entry from stabs. Sun CC specific.
-struct slist {
- // String table index.
- unsigned int n_strx;
- // Stab type.
- unsigned char n_type;
- char n_other;
- short n_desc;
- unsigned long n_value;
-};
-
-// Symbol table entry
-struct SymbolEntry {
- // Offset from the start of the file.
- GElf_Addr offset;
- // Function size.
- GElf_Word size;
-};
-
-// Infomation of a line.
-struct LineInfo {
- // Offset from start of the function.
- // Load from stab symbol.
- GElf_Off rva_to_func;
- // Offset from base of the loading binary.
- GElf_Off rva_to_base;
- // Size of the line.
- // The first line: equals to rva_to_func.
- // The other lines: the difference of rva_to_func of the line and
- // rva_to_func of the previous N_SLINE.
- uint32_t size;
- // Line number.
- uint32_t line_num;
-};
-
-// Information of a function.
-struct FuncInfo {
- // Name of the function.
- const char *name;
- // Offset from the base of the loading address.
- GElf_Off rva_to_base;
- // Virtual address of the function.
- // Load from stab symbol.
- GElf_Addr addr;
- // Size of the function.
- // Equal to rva_to_func of the last function line.
- uint32_t size;
- // Total size of stack parameters.
- uint32_t stack_param_size;
- // Line information array.
- std::vector<struct LineInfo> line_info;
-};
-
-// Information of a source file.
-struct SourceFileInfo {
- // Name of the source file.
- const char *name;
- // Starting address of the source file.
- GElf_Addr addr;
- // Id of the source file.
- int source_id;
- // Functions information.
- std::vector<struct FuncInfo> func_info;
-};
-
-struct CompareString {
- bool operator()(const char *s1, const char *s2) const {
- return strcmp(s1, s2) < 0;
- }
-};
-
-typedef std::map<const char *, struct SymbolEntry *, CompareString> SymbolMap;
-
-// Information of a symbol table.
-// This is the root of all types of symbol.
-struct SymbolInfo {
- std::vector<struct SourceFileInfo> source_file_info;
- // Symbols information.
- SymbolMap symbol_entries;
-};
-
-// Stab section name.
-const char *kStabName = ".stab";
-
-// Stab str section name.
-const char *kStabStrName = ".stabstr";
-
-// Symtab section name.
-const char *kSymtabName = ".symtab";
-
-// Strtab section name.
-const char *kStrtabName = ".strtab";
-
-// Default buffer lenght for demangle.
-const int demangleLen = 20000;
-
-// Offset to the string table.
-uint64_t stringOffset = 0;
-
-// Update the offset to the start of the string index of the next
-// object module for every N_ENDM stabs.
-inline void RecalculateOffset(struct slist* cur_list, char *stabstr) {
- while ((--cur_list)->n_strx == 0) ;
- stringOffset += cur_list->n_strx;
-
- char *temp = stabstr + stringOffset;
- while (*temp != '\0') {
- ++stringOffset;
- ++temp;
- }
- // Skip the extra '\0'
- ++stringOffset;
-}
-
-// Demangle using demangle library on Solaris.
-std::string Demangle(const char *mangled) {
- int status = 0;
- std::string str(mangled);
- char *demangled = (char *)malloc(demangleLen);
-
- if (!demangled) {
- fprintf(stderr, "no enough memory.\n");
- goto out;
- }
-
- if ((status = cplus_demangle(mangled, demangled, demangleLen)) ==
- DEMANGLE_ESPACE) {
- fprintf(stderr, "incorrect demangle.\n");
- goto out;
- }
-
- str = demangled;
- free(demangled);
-
-out:
- return str;
-}
-
-bool WriteFormat(int fd, const char *fmt, ...) {
- va_list list;
- char buffer[4096];
- ssize_t expected, written;
- va_start(list, fmt);
- vsnprintf(buffer, sizeof(buffer), fmt, list);
- expected = strlen(buffer);
- written = write(fd, buffer, strlen(buffer));
- va_end(list);
- return expected == written;
-}
-
-bool IsValidElf(const GElf_Ehdr *elf_header) {
- return memcmp(elf_header, ELFMAG, SELFMAG) == 0;
-}
-
-static bool FindSectionByName(Elf *elf, const char *name,
- int shstrndx,
- GElf_Shdr *shdr) {
- assert(name != NULL);
-
- if (strlen(name) == 0)
- return false;
-
- Elf_Scn *scn = NULL;
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- if (gelf_getshdr(scn, shdr) == (GElf_Shdr *)0) {
- fprintf(stderr, "failed to read section header: %s\n", elf_errmsg(0));
- return false;
- }
-
- const char *section_name = elf_strptr(elf, shstrndx, shdr->sh_name);
- if (!section_name) {
- fprintf(stderr, "Section name error: %s\n", elf_errmsg(-1));
- continue;
- }
-
- if (strcmp(section_name, name) == 0)
- return true;
- }
-
- return false;
-}
-
-// The parameter size is used for FPO-optimized code, and
-// this is all tied up with the debugging data for Windows x86.
-// Set it to 0 on Solaris.
-int LoadStackParamSize(struct slist *list,
- struct slist *list_end,
- struct FuncInfo *func_info) {
- struct slist *cur_list = list;
- int step = 1;
- while (cur_list < list_end && cur_list->n_type == N_PSYM) {
- ++cur_list;
- ++step;
- }
-
- func_info->stack_param_size = 0;
- return step;
-}
-
-int LoadLineInfo(struct slist *list,
- struct slist *list_end,
- struct FuncInfo *func_info) {
- struct slist *cur_list = list;
- do {
- // Skip non line information.
- while (cur_list < list_end && cur_list->n_type != N_SLINE) {
- // Only exit when got another function, or source file, or end stab.
- if (cur_list->n_type == N_FUN || cur_list->n_type == N_SO ||
- cur_list->n_type == N_ENDM) {
- return cur_list - list;
- }
- ++cur_list;
- }
- struct LineInfo line;
- while (cur_list < list_end && cur_list->n_type == N_SLINE) {
- line.rva_to_func = cur_list->n_value;
- // n_desc is a signed short
- line.line_num = (unsigned short)cur_list->n_desc;
- func_info->line_info.push_back(line);
- ++cur_list;
- }
- if (cur_list == list_end && cur_list->n_type == N_ENDM)
- break;
- } while (list < list_end);
-
- return cur_list - list;
-}
-
-int LoadFuncSymbols(struct slist *list,
- struct slist *list_end,
- char *stabstr,
- GElf_Word base,
- struct SourceFileInfo *source_file_info) {
- struct slist *cur_list = list;
- assert(cur_list->n_type == N_SO);
- ++cur_list;
-
- source_file_info->func_info.clear();
- while (cur_list < list_end) {
- // Go until the function symbol.
- while (cur_list < list_end && cur_list->n_type != N_FUN) {
- if (cur_list->n_type == N_SO) {
- return cur_list - list;
- }
- ++cur_list;
- if (cur_list->n_type == N_ENDM)
- RecalculateOffset(cur_list, stabstr);
- continue;
- }
- while (cur_list->n_type == N_FUN) {
- struct FuncInfo func_info;
- memset(&func_info, 0, sizeof(func_info));
- func_info.name = stabstr + cur_list->n_strx + stringOffset;
- // The n_value field is always 0 from stab generated by Sun CC.
- // TODO(Alfred): Find the correct value.
- func_info.addr = cur_list->n_value;
- ++cur_list;
- if (cur_list->n_type == N_ENDM)
- RecalculateOffset(cur_list, stabstr);
- if (cur_list->n_type != N_ESYM && cur_list->n_type != N_ISYM &&
- cur_list->n_type != N_FUN) {
- // Stack parameter size.
- cur_list += LoadStackParamSize(cur_list, list_end, &func_info);
- // Line info.
- cur_list += LoadLineInfo(cur_list, list_end, &func_info);
- }
- if (cur_list < list_end && cur_list->n_type == N_ENDM)
- RecalculateOffset(cur_list, stabstr);
- // Functions in this module should have address bigger than the module
- // starting address.
- //
- // These two values are always 0 with Sun CC.
- // TODO(Alfred): Get the correct value or remove the condition statement.
- if (func_info.addr >= source_file_info->addr) {
- source_file_info->func_info.push_back(func_info);
- }
- }
- }
- return cur_list - list;
-}
-
-// Compute size and rva information based on symbols loaded from stab section.
-bool ComputeSizeAndRVA(struct SymbolInfo *symbols) {
- std::vector<struct SourceFileInfo> *sorted_files =
- &(symbols->source_file_info);
- SymbolMap *symbol_entries = &(symbols->symbol_entries);
- for (size_t i = 0; i < sorted_files->size(); ++i) {
- struct SourceFileInfo &source_file = (*sorted_files)[i];
- std::vector<struct FuncInfo> *sorted_functions = &(source_file.func_info);
- int func_size = sorted_functions->size();
-
- for (size_t j = 0; j < func_size; ++j) {
- struct FuncInfo &func_info = (*sorted_functions)[j];
- int line_count = func_info.line_info.size();
-
- // Discard the ending part of the name.
- std::string func_name(func_info.name);
- std::string::size_type last_colon = func_name.find_first_of(':');
- if (last_colon != std::string::npos)
- func_name = func_name.substr(0, last_colon);
-
- // Fine the symbol offset from the loading address and size by name.
- SymbolMap::const_iterator it = symbol_entries->find(func_name.c_str());
- if (it->second) {
- func_info.rva_to_base = it->second->offset;
- func_info.size = (line_count == 0) ? 0 : it->second->size;
- } else {
- func_info.rva_to_base = 0;
- func_info.size = 0;
- }
-
- // Compute function and line size.
- for (size_t k = 0; k < line_count; ++k) {
- struct LineInfo &line_info = func_info.line_info[k];
-
- line_info.rva_to_base = line_info.rva_to_func + func_info.rva_to_base;
- if (k == line_count - 1) {
- line_info.size = func_info.size - line_info.rva_to_func;
- } else {
- struct LineInfo &next_line = func_info.line_info[k + 1];
- line_info.size = next_line.rva_to_func - line_info.rva_to_func;
- }
- } // for each line.
- } // for each function.
- } // for each source file.
- for (SymbolMap::iterator it = symbol_entries->begin();
- it != symbol_entries->end(); ++it) {
- free(it->second);
- }
- return true;
-}
-
-bool LoadAllSymbols(const GElf_Shdr *stab_section,
- const GElf_Shdr *stabstr_section,
- GElf_Word base,
- struct SymbolInfo *symbols) {
- if (stab_section == NULL || stabstr_section == NULL)
- return false;
-
- char *stabstr =
- reinterpret_cast<char *>(stabstr_section->sh_offset + base);
- struct slist *lists =
- reinterpret_cast<struct slist *>(stab_section->sh_offset + base);
- int nstab = stab_section->sh_size / sizeof(struct slist);
- int source_id = 0;
-
- // First pass, load all symbols from the object file.
- for (int i = 0; i < nstab; ) {
- int step = 1;
- struct slist *cur_list = lists + i;
- if (cur_list->n_type == N_SO) {
- // FUNC <address> <size> <param_stack_size> <function>
- struct SourceFileInfo source_file_info;
- source_file_info.name = stabstr + cur_list->n_strx + stringOffset;
- // The n_value field is always 0 from stab generated by Sun CC.
- // TODO(Alfred): Find the correct value.
- source_file_info.addr = cur_list->n_value;
- if (strchr(source_file_info.name, '.'))
- source_file_info.source_id = source_id++;
- else
- source_file_info.source_id = -1;
- step = LoadFuncSymbols(cur_list, lists + nstab - 1, stabstr,
- base, &source_file_info);
- symbols->source_file_info.push_back(source_file_info);
- }
- i += step;
- }
- // Second pass, compute the size of functions and lines.
- return ComputeSizeAndRVA(symbols);
-}
-
-bool LoadSymbols(Elf *elf, GElf_Ehdr *elf_header, struct SymbolInfo *symbols,
- void *obj_base) {
- GElf_Word base = reinterpret_cast<GElf_Word>(obj_base);
-
- const GElf_Shdr *sections =
- reinterpret_cast<GElf_Shdr *>(elf_header->e_shoff + base);
- GElf_Shdr stab_section;
- if (!FindSectionByName(elf, kStabName, elf_header->e_shstrndx,
- &stab_section)) {
- fprintf(stderr, "Stab section not found.\n");
- return false;
- }
- GElf_Shdr stabstr_section;
- if (!FindSectionByName(elf, kStabStrName, elf_header->e_shstrndx,
- &stabstr_section)) {
- fprintf(stderr, "Stabstr section not found.\n");
- return false;
- }
- GElf_Shdr symtab_section;
- if (!FindSectionByName(elf, kSymtabName, elf_header->e_shstrndx,
- &symtab_section)) {
- fprintf(stderr, "Symtab section not found.\n");
- return false;
- }
- GElf_Shdr strtab_section;
- if (!FindSectionByName(elf, kStrtabName, elf_header->e_shstrndx,
- &strtab_section)) {
- fprintf(stderr, "Strtab section not found.\n");
- return false;
- }
-
- Elf_Sym *symbol = (Elf_Sym *)((char *)base + symtab_section.sh_offset);
- for (int i = 0; i < symtab_section.sh_size/symtab_section.sh_entsize; ++i) {
- struct SymbolEntry *symbol_entry =
- (struct SymbolEntry *)malloc(sizeof(struct SymbolEntry));
- const char *name = reinterpret_cast<char *>(
- strtab_section.sh_offset + (GElf_Word)base + symbol->st_name);
- symbol_entry->offset = symbol->st_value;
- symbol_entry->size = symbol->st_size;
- symbols->symbol_entries.insert(make_pair(name, symbol_entry));
- ++symbol;
- }
-
-
- // Load symbols.
- return LoadAllSymbols(&stab_section, &stabstr_section, base, symbols);
-}
-
-bool WriteModuleInfo(int fd, GElf_Half arch, const std::string &obj_file) {
- const char *arch_name = NULL;
- if (arch == EM_386)
- arch_name = "x86";
- else if (arch == EM_X86_64)
- arch_name = "x86_64";
- else if (arch == EM_SPARC32PLUS)
- arch_name = "SPARC_32+";
- else {
- printf("Please add more ARCH support\n");
- return false;
- }
-
- unsigned char identifier[16];
- google_breakpad::FileID file_id(obj_file.c_str());
- if (file_id.ElfFileIdentifier(identifier)) {
- char identifier_str[40];
- file_id.ConvertIdentifierToString(identifier,
- identifier_str, sizeof(identifier_str));
- std::string filename = obj_file;
- size_t slash_pos = obj_file.find_last_of("/");
- if (slash_pos != std::string::npos)
- filename = obj_file.substr(slash_pos + 1);
- return WriteFormat(fd, "MODULE solaris %s %s %s\n", arch_name,
- identifier_str, filename.c_str());
- }
- return false;
-}
-
-bool WriteSourceFileInfo(int fd, const struct SymbolInfo &symbols) {
- for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
- if (symbols.source_file_info[i].source_id != -1) {
- const char *name = symbols.source_file_info[i].name;
- if (!WriteFormat(fd, "FILE %d %s\n",
- symbols.source_file_info[i].source_id, name))
- return false;
- }
- }
- return true;
-}
-
-bool WriteOneFunction(int fd, int source_id,
- const struct FuncInfo &func_info){
- // Discard the ending part of the name.
- std::string func_name(func_info.name);
- std::string::size_type last_colon = func_name.find_last_of(':');
- if (last_colon != std::string::npos)
- func_name = func_name.substr(0, last_colon);
- func_name = Demangle(func_name.c_str());
-
- if (func_info.size <= 0)
- return true;
-
- // rva_to_base could be unsigned long(32 bit) or unsigned long long(64 bit).
- if (WriteFormat(fd, "FUNC %llx %x %d %s\n",
- (long long)func_info.rva_to_base,
- func_info.size,
- func_info.stack_param_size,
- func_name.c_str())) {
- for (size_t i = 0; i < func_info.line_info.size(); ++i) {
- const struct LineInfo &line_info = func_info.line_info[i];
- if (line_info.line_num == 0)
- return true;
- if (!WriteFormat(fd, "%llx %x %d %d\n",
- (long long)line_info.rva_to_base,
- line_info.size,
- line_info.line_num,
- source_id))
- return false;
- }
- return true;
- }
- return false;
-}
-
-bool WriteFunctionInfo(int fd, const struct SymbolInfo &symbols) {
- for (size_t i = 0; i < symbols.source_file_info.size(); ++i) {
- const struct SourceFileInfo &file_info = symbols.source_file_info[i];
- for (size_t j = 0; j < file_info.func_info.size(); ++j) {
- const struct FuncInfo &func_info = file_info.func_info[j];
- if (!WriteOneFunction(fd, file_info.source_id, func_info))
- return false;
- }
- }
- return true;
-}
-
-bool DumpStabSymbols(int fd, const struct SymbolInfo &symbols) {
- return WriteSourceFileInfo(fd, symbols) &&
- WriteFunctionInfo(fd, symbols);
-}
-
-//
-// FDWrapper
-//
-// Wrapper class to make sure opened file is closed.
-//
-class FDWrapper {
- public:
- explicit FDWrapper(int fd) :
- fd_(fd) {
- }
- ~FDWrapper() {
- if (fd_ != -1)
- close(fd_);
- }
- int get() {
- return fd_;
- }
- int release() {
- int fd = fd_;
- fd_ = -1;
- return fd;
- }
- private:
- int fd_;
-};
-
-//
-// MmapWrapper
-//
-// Wrapper class to make sure mapped regions are unmapped.
-//
-class MmapWrapper {
- public:
- MmapWrapper(void *mapped_address, size_t mapped_size) :
- base_(mapped_address), size_(mapped_size) {
- }
- ~MmapWrapper() {
- if (base_ != NULL) {
- assert(size_ > 0);
- munmap((char *)base_, size_);
- }
- }
- void release() {
- base_ = NULL;
- size_ = 0;
- }
-
- private:
- void *base_;
- size_t size_;
-};
-
-} // namespace
-
-namespace google_breakpad {
-
-class AutoElfEnder {
- public:
- AutoElfEnder(Elf *elf) : elf_(elf) {}
- ~AutoElfEnder() { if (elf_) elf_end(elf_); }
- private:
- Elf *elf_;
-};
-
-
-bool DumpSymbols::WriteSymbolFile(const std::string &obj_file, int sym_fd) {
- if (elf_version(EV_CURRENT) == EV_NONE) {
- fprintf(stderr, "elf_version() failed: %s\n", elf_errmsg(0));
- return false;
- }
-
- int obj_fd = open(obj_file.c_str(), O_RDONLY);
- if (obj_fd < 0)
- return false;
- FDWrapper obj_fd_wrapper(obj_fd);
- struct stat st;
- if (fstat(obj_fd, &st) != 0 && st.st_size <= 0)
- return false;
- void *obj_base = mmap(NULL, st.st_size,
- PROT_READ, MAP_PRIVATE, obj_fd, 0);
- if (obj_base == MAP_FAILED)
- return false;
- MmapWrapper map_wrapper(obj_base, st.st_size);
- GElf_Ehdr elf_header;
- Elf *elf = elf_begin(obj_fd, ELF_C_READ, NULL);
- AutoElfEnder elfEnder(elf);
-
- if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) {
- fprintf(stderr, "failed to read elf header: %s\n", elf_errmsg(-1));
- return false;
- }
-
- if (!IsValidElf(&elf_header)) {
- fprintf(stderr, "header magic doesn't match\n");
- return false;
- }
- struct SymbolInfo symbols;
- if (!LoadSymbols(elf, &elf_header, &symbols, obj_base))
- return false;
- // Write to symbol file.
- if (WriteModuleInfo(sym_fd, elf_header.e_machine, obj_file) &&
- DumpStabSymbols(sym_fd, symbols))
- return true;
-
- return false;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.h b/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.h
deleted file mode 100644
index 7f4baadcf..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/dump_symbols.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-//
-// dump_symbols.cc: Implements a Solaris stab debugging format dumper.
-//
-// Author: Alfred Peng
-
-#ifndef COMMON_SOLARIS_DUMP_SYMBOLS_H__
-#define COMMON_SOLARIS_DUMP_SYMBOLS_H__
-
-#include <string>
-
-namespace google_breakpad {
-
-class DumpSymbols {
- public:
- bool WriteSymbolFile(const std::string &obj_file,
- int sym_fd);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_SOLARIS_DUMP_SYMBOLS_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc
deleted file mode 100644
index 643a14629..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// 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.
-
-// file_id.cc: Return a unique identifier for a file
-//
-// See file_id.h for documentation
-//
-// Author: Alfred Peng
-
-#include <elf.h>
-#include <fcntl.h>
-#include <gelf.h>
-#include <sys/mman.h>
-#include <sys/ksyms.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cassert>
-#include <cstdio>
-
-#include "common/md5.h"
-#include "common/solaris/file_id.h"
-#include "common/solaris/message_output.h"
-#include "google_breakpad/common/minidump_format.h"
-
-namespace google_breakpad {
-
-class AutoElfEnder {
- public:
- AutoElfEnder(Elf *elf) : elf_(elf) {}
- ~AutoElfEnder() { if (elf_) elf_end(elf_); }
- private:
- Elf *elf_;
-};
-
-// Find the text section in elf object file.
-// Return the section start address and the size.
-static bool FindElfTextSection(int fd, const void *elf_base,
- const void **text_start,
- int *text_size) {
- assert(text_start);
- assert(text_size);
-
- *text_start = NULL;
- *text_size = 0;
-
- if (elf_version(EV_CURRENT) == EV_NONE) {
- print_message2(2, "elf_version() failed: %s\n", elf_errmsg(0));
- return false;
- }
-
- GElf_Ehdr elf_header;
- lseek(fd, 0L, 0);
- Elf *elf = elf_begin(fd, ELF_C_READ, NULL);
- AutoElfEnder elfEnder(elf);
-
- if (gelf_getehdr(elf, &elf_header) == (GElf_Ehdr *)NULL) {
- print_message2(2, "failed to read elf header: %s\n", elf_errmsg(-1));
- return false;
- }
-
- if (elf_header.e_ident[EI_MAG0] != ELFMAG0 ||
- elf_header.e_ident[EI_MAG1] != ELFMAG1 ||
- elf_header.e_ident[EI_MAG2] != ELFMAG2 ||
- elf_header.e_ident[EI_MAG3] != ELFMAG3) {
- print_message1(2, "header magic doesn't match\n");
- return false;
- }
-
- static const char kTextSectionName[] = ".text";
- const GElf_Shdr *text_section = NULL;
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr;
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- if (gelf_getshdr(scn, &shdr) == (GElf_Shdr *)0) {
- print_message2(2, "failed to read section header: %s\n", elf_errmsg(0));
- return false;
- }
-
- if (shdr.sh_type == SHT_PROGBITS) {
- const char *section_name = elf_strptr(elf, elf_header.e_shstrndx,
- shdr.sh_name);
- if (!section_name) {
- print_message2(2, "Section name error: %s\n", elf_errmsg(-1));
- continue;
- }
-
- if (strcmp(section_name, kTextSectionName) == 0) {
- text_section = &shdr;
- break;
- }
- }
- }
- if (text_section != NULL && text_section->sh_size > 0) {
- *text_start = (char *)elf_base + text_section->sh_offset;
- *text_size = text_section->sh_size;
- return true;
- }
-
- return false;
-}
-
-FileID::FileID(const char *path) {
- strcpy(path_, path);
-}
-
-class AutoCloser {
- public:
- AutoCloser(int fd) : fd_(fd) {}
- ~AutoCloser() { if (fd_) close(fd_); }
- private:
- int fd_;
-};
-
-bool FileID::ElfFileIdentifier(unsigned char identifier[16]) {
- int fd = 0;
- if ((fd = open(path_, O_RDONLY)) < 0)
- return false;
-
- AutoCloser autocloser(fd);
- struct stat st;
- if (fstat(fd, &st) != 0 || st.st_size <= 0)
- return false;
-
- void *base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (base == MAP_FAILED)
- return false;
-
- bool success = false;
- const void *text_section = NULL;
- int text_size = 0;
-
- if (FindElfTextSection(fd, base, &text_section, &text_size)) {
- MD5Context md5;
- MD5Init(&md5);
- MD5Update(&md5, (const unsigned char *)text_section, text_size);
- MD5Final(identifier, &md5);
- success = true;
- }
-
- munmap((char *)base, st.st_size);
- return success;
-}
-
-// static
-bool FileID::ConvertIdentifierToString(const unsigned char identifier[16],
- char *buffer, int buffer_length) {
- if (buffer_length < 34)
- return false;
-
- int buffer_idx = 0;
- for (int idx = 0; idx < 16; ++idx) {
- int hi = (identifier[idx] >> 4) & 0x0F;
- int lo = (identifier[idx]) & 0x0F;
-
- buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
- buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
- }
-
- // Add an extra "0" by the end.
- buffer[buffer_idx++] = '0';
-
- // NULL terminate
- buffer[buffer_idx] = 0;
-
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.h b/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.h
deleted file mode 100644
index 375e85751..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/file_id.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// 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.
-
-// file_id.h: Return a unique identifier for a file
-//
-// Author: Alfred Peng
-
-#ifndef COMMON_SOLARIS_FILE_ID_H__
-#define COMMON_SOLARIS_FILE_ID_H__
-
-#include <limits.h>
-
-namespace google_breakpad {
-
-class FileID {
- public:
- FileID(const char *path);
- ~FileID() {};
-
- // Load the identifier for the elf file path specified in the constructor into
- // |identifier|. Return false if the identifier could not be created for the
- // file.
- // The current implementation will return the MD5 hash of the file's bytes.
- bool ElfFileIdentifier(unsigned char identifier[16]);
-
- // Convert the |identifier| data to a NULL terminated string. The string will
- // be formatted as a MDCVInfoPDB70 struct.
- // The |buffer| should be at least 34 bytes long to receive all of the data
- // and termination. Shorter buffers will return false.
- static bool ConvertIdentifierToString(const unsigned char identifier[16],
- char *buffer, int buffer_length);
-
- private:
- // Storage for the path specified
- char path_[PATH_MAX];
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_SOLARIS_FILE_ID_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.cc b/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.cc
deleted file mode 100644
index e9e6c6f5d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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.
-
-// Author: Alfred Peng
-
-#include <cassert>
-#include <ctime>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "common/solaris/guid_creator.h"
-
-//
-// GUIDGenerator
-//
-// This class is used to generate random GUID.
-// Currently use random number to generate a GUID. This should be OK since
-// we don't expect crash to happen very offen.
-//
-class GUIDGenerator {
- public:
- GUIDGenerator() {
- srandom(time(NULL));
- }
-
- bool CreateGUID(GUID *guid) const {
- guid->data1 = random();
- guid->data2 = (uint16_t)(random());
- guid->data3 = (uint16_t)(random());
- *reinterpret_cast<uint32_t*>(&guid->data4[0]) = random();
- *reinterpret_cast<uint32_t*>(&guid->data4[4]) = random();
- return true;
- }
-};
-
-// Guid generator.
-const GUIDGenerator kGuidGenerator;
-
-bool CreateGUID(GUID *guid) {
- return kGuidGenerator.CreateGUID(guid);
-}
-
-// Parse guid to string.
-bool GUIDToString(const GUID *guid, char *buf, int buf_len) {
- // Should allow more space the the max length of GUID.
- assert(buf_len > kGUIDStringLength);
- int num = snprintf(buf, buf_len, kGUIDFormatString,
- guid->data1, guid->data2, guid->data3,
- *reinterpret_cast<const uint32_t *>(&(guid->data4[0])),
- *reinterpret_cast<const uint32_t *>(&(guid->data4[4])));
- if (num != kGUIDStringLength)
- return false;
-
- buf[num] = '\0';
- return true;
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.h b/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.h
deleted file mode 100644
index 4aee3a1c2..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/guid_creator.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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.
-
-// Author: Alfred Peng
-
-#ifndef COMMON_SOLARIS_GUID_CREATOR_H__
-#define COMMON_SOLARIS_GUID_CREATOR_H__
-
-#include "google_breakpad/common/minidump_format.h"
-
-typedef MDGUID GUID;
-
-// Format string for parsing GUID.
-#define kGUIDFormatString "%08x-%04x-%04x-%08x-%08x"
-// Length of GUID string. Don't count the ending '\0'.
-#define kGUIDStringLength 36
-
-// Create a guid.
-bool CreateGUID(GUID *guid);
-
-// Get the string from guid.
-bool GUIDToString(const GUID *guid, char *buf, int buf_len);
-
-#endif // COMMON_SOLARIS_GUID_CREATOR_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/message_output.h b/toolkit/crashreporter/google-breakpad/src/common/solaris/message_output.h
deleted file mode 100644
index 3e3b1d465..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/message_output.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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.
-
-// Author: Alfred Peng
-
-#ifndef COMMON_SOLARIS_MESSAGE_OUTPUT_H__
-#define COMMON_SOLARIS_MESSAGE_OUTPUT_H__
-
-namespace google_breakpad {
-
-const int MESSAGE_MAX = 1000;
-
-// Message output macros.
-// snprintf doesn't operate heap on Solaris, while printf and fprintf do.
-// Use snprintf here to avoid heap allocation.
-#define print_message1(std, message) \
- char buffer[MESSAGE_MAX]; \
- int len = snprintf(buffer, MESSAGE_MAX, message); \
- write(std, buffer, len)
-
-#define print_message2(std, message, para) \
- char buffer[MESSAGE_MAX]; \
- int len = snprintf(buffer, MESSAGE_MAX, message, para); \
- write(std, buffer, len);
-
-} // namespace google_breakpad
-
-#endif // COMMON_SOLARIS_MESSAGE_OUTPUT_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/solaris/moz.build b/toolkit/crashreporter/google-breakpad/src/common/solaris/moz.build
deleted file mode 100644
index c91b96fc7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/solaris/moz.build
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-UNIFIED_SOURCES += [
- 'dump_symbols.cc',
- 'file_id.cc',
- 'guid_creator.cc',
-]
-
-HostLibrary('host_breakpad_solaris_common_s')
-
-Library('breakpad_solaris_common_s')
-
-# not compiling http_upload.cc currently
-# since it depends on libcurl
-HOST_SOURCES += [
- 'dump_symbols.cc',
- 'file_id.cc',
- 'guid_creator.cc',
-]
-HOST_CXXFLAGS += [
- '-O2',
- '-g',
-]
-
-FINAL_LIBRARY = 'xul'
-
-LOCAL_INCLUDES += [
- '../..',
-]
-
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
deleted file mode 100644
index 6019fc7ee..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.cc
+++ /dev/null
@@ -1,315 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// This file implements the google_breakpad::StabsReader class.
-// See stabs_reader.h.
-
-#include "common/stabs_reader.h"
-
-#include <assert.h>
-#include <stab.h>
-#include <string.h>
-
-#include <string>
-
-#include "common/using_std_string.h"
-
-using std::vector;
-
-namespace google_breakpad {
-
-StabsReader::EntryIterator::EntryIterator(const ByteBuffer *buffer,
- bool big_endian, size_t value_size)
- : value_size_(value_size), cursor_(buffer, big_endian) {
- // Actually, we could handle weird sizes just fine, but they're
- // probably mistakes --- expressed in bits, say.
- assert(value_size == 4 || value_size == 8);
- entry_.index = 0;
- Fetch();
-}
-
-void StabsReader::EntryIterator::Fetch() {
- cursor_
- .Read(4, false, &entry_.name_offset)
- .Read(1, false, &entry_.type)
- .Read(1, false, &entry_.other)
- .Read(2, false, &entry_.descriptor)
- .Read(value_size_, false, &entry_.value);
- entry_.at_end = !cursor_;
-}
-
-StabsReader::StabsReader(const uint8_t *stab, size_t stab_size,
- const uint8_t *stabstr, size_t stabstr_size,
- bool big_endian, size_t value_size, bool unitized,
- StabsHandler *handler)
- : entries_(stab, stab_size),
- strings_(stabstr, stabstr_size),
- iterator_(&entries_, big_endian, value_size),
- unitized_(unitized),
- handler_(handler),
- string_offset_(0),
- next_cu_string_offset_(0),
- current_source_file_(NULL) { }
-
-const char *StabsReader::SymbolString() {
- ptrdiff_t offset = string_offset_ + iterator_->name_offset;
- if (offset < 0 || (size_t) offset >= strings_.Size()) {
- handler_->Warning("symbol %d: name offset outside the string section\n",
- iterator_->index);
- // Return our null string, to keep our promise about all names being
- // taken from the string section.
- offset = 0;
- }
- return reinterpret_cast<const char *>(strings_.start + offset);
-}
-
-bool StabsReader::Process() {
- while (!iterator_->at_end) {
- if (iterator_->type == N_SO) {
- if (! ProcessCompilationUnit())
- return false;
- } else if (iterator_->type == N_UNDF && unitized_) {
- // In unitized STABS (including Linux STABS, and pretty much anything
- // else that puts STABS data in sections), at the head of each
- // compilation unit's entries there is an N_UNDF stab giving the
- // number of symbols in the compilation unit, and the number of bytes
- // that compilation unit's strings take up in the .stabstr section.
- // Each CU's strings are separate; the n_strx values are offsets
- // within the current CU's portion of the .stabstr section.
- //
- // As an optimization, the GNU linker combines all the
- // compilation units into one, with a single N_UNDF at the
- // beginning. However, other linkers, like Gold, do not perform
- // this optimization.
- string_offset_ = next_cu_string_offset_;
- next_cu_string_offset_ = iterator_->value;
- ++iterator_;
- }
-#if defined(HAVE_MACH_O_NLIST_H)
- // Export symbols in Mach-O binaries look like this.
- // This is necessary in order to be able to dump symbols
- // from OS X system libraries.
- else if ((iterator_->type & N_STAB) == 0 &&
- (iterator_->type & N_TYPE) == N_SECT) {
- ProcessExtern();
- }
-#endif
- else {
- ++iterator_;
- }
- }
- return true;
-}
-
-bool StabsReader::ProcessCompilationUnit() {
- assert(!iterator_->at_end && iterator_->type == N_SO);
-
- // There may be an N_SO entry whose name ends with a slash,
- // indicating the directory in which the compilation occurred.
- // The build directory defaults to NULL.
- const char *build_directory = NULL;
- {
- const char *name = SymbolString();
- if (name[0] && name[strlen(name) - 1] == '/') {
- build_directory = name;
- ++iterator_;
- }
- }
-
- // We expect to see an N_SO entry with a filename next, indicating
- // the start of the compilation unit.
- {
- if (iterator_->at_end || iterator_->type != N_SO)
- return true;
- const char *name = SymbolString();
- if (name[0] == '\0') {
- // This seems to be a stray end-of-compilation-unit marker;
- // consume it, but don't report the end, since we didn't see a
- // beginning.
- ++iterator_;
- return true;
- }
- current_source_file_ = name;
- }
-
- if (! handler_->StartCompilationUnit(current_source_file_,
- iterator_->value,
- build_directory))
- return false;
-
- ++iterator_;
-
- // The STABS documentation says that some compilers may emit
- // additional N_SO entries with names immediately following the
- // first, and that they should be ignored. However, the original
- // Breakpad STABS reader doesn't ignore them, so we won't either.
-
- // Process the body of the compilation unit, up to the next N_SO.
- while (!iterator_->at_end && iterator_->type != N_SO) {
- if (iterator_->type == N_FUN) {
- if (! ProcessFunction())
- return false;
- } else if (iterator_->type == N_SLINE) {
- // Mac OS X STABS place SLINE records before functions.
- Line line;
- // The value of an N_SLINE entry that appears outside a function is
- // the absolute address of the line.
- line.address = iterator_->value;
- line.filename = current_source_file_;
- // The n_desc of a N_SLINE entry is the line number. It's a
- // signed 16-bit field; line numbers from 32768 to 65535 are
- // stored as n-65536.
- line.number = (uint16_t) iterator_->descriptor;
- queued_lines_.push_back(line);
- ++iterator_;
- } else if (iterator_->type == N_SOL) {
- current_source_file_ = SymbolString();
- ++iterator_;
- } else {
- // Ignore anything else.
- ++iterator_;
- }
- }
-
- // An N_SO with an empty name indicates the end of the compilation
- // unit. Default to zero.
- uint64_t ending_address = 0;
- if (!iterator_->at_end) {
- assert(iterator_->type == N_SO);
- const char *name = SymbolString();
- if (name[0] == '\0') {
- ending_address = iterator_->value;
- ++iterator_;
- }
- }
-
- if (! handler_->EndCompilationUnit(ending_address))
- return false;
-
- queued_lines_.clear();
-
- return true;
-}
-
-bool StabsReader::ProcessFunction() {
- assert(!iterator_->at_end && iterator_->type == N_FUN);
-
- uint64_t function_address = iterator_->value;
- // The STABS string for an N_FUN entry is the name of the function,
- // followed by a colon, followed by type information for the
- // function. We want to pass the name alone to StartFunction.
- const char *stab_string = SymbolString();
- const char *name_end = strchr(stab_string, ':');
- if (! name_end)
- name_end = stab_string + strlen(stab_string);
- string name(stab_string, name_end - stab_string);
- if (! handler_->StartFunction(name, function_address))
- return false;
- ++iterator_;
-
- // If there were any SLINE records given before the function, report them now.
- for (vector<Line>::const_iterator it = queued_lines_.begin();
- it != queued_lines_.end(); it++) {
- if (!handler_->Line(it->address, it->filename, it->number))
- return false;
- }
- queued_lines_.clear();
-
- while (!iterator_->at_end) {
- if (iterator_->type == N_SO || iterator_->type == N_FUN)
- break;
- else if (iterator_->type == N_SLINE) {
- // The value of an N_SLINE entry is the offset of the line from
- // the function's start address.
- uint64_t line_address = function_address + iterator_->value;
- // The n_desc of a N_SLINE entry is the line number. It's a
- // signed 16-bit field; line numbers from 32768 to 65535 are
- // stored as n-65536.
- uint16_t line_number = iterator_->descriptor;
- if (! handler_->Line(line_address, current_source_file_, line_number))
- return false;
- ++iterator_;
- } else if (iterator_->type == N_SOL) {
- current_source_file_ = SymbolString();
- ++iterator_;
- } else
- // Ignore anything else.
- ++iterator_;
- }
-
- // We've reached the end of the function. See if we can figure out its
- // ending address.
- uint64_t ending_address = 0;
- if (!iterator_->at_end) {
- assert(iterator_->type == N_SO || iterator_->type == N_FUN);
- if (iterator_->type == N_FUN) {
- const char *symbol_name = SymbolString();
- if (symbol_name[0] == '\0') {
- // An N_FUN entry with no name is a terminator for this function;
- // its value is the function's size.
- ending_address = function_address + iterator_->value;
- ++iterator_;
- } else {
- // An N_FUN entry with a name is the next function, and we can take
- // its value as our ending address. Don't advance the iterator, as
- // we'll use this symbol to start the next function as well.
- ending_address = iterator_->value;
- }
- } else {
- // An N_SO entry could be an end-of-compilation-unit marker, or the
- // start of the next compilation unit, but in either case, its value
- // is our ending address. We don't advance the iterator;
- // ProcessCompilationUnit will decide what to do with this symbol.
- ending_address = iterator_->value;
- }
- }
-
- if (! handler_->EndFunction(ending_address))
- return false;
-
- return true;
-}
-
-bool StabsReader::ProcessExtern() {
-#if defined(HAVE_MACH_O_NLIST_H)
- assert(!iterator_->at_end &&
- (iterator_->type & N_STAB) == 0 &&
- (iterator_->type & N_TYPE) == N_SECT);
-#endif
-
- // TODO(mark): only do symbols in the text section?
- if (!handler_->Extern(SymbolString(), iterator_->value))
- return false;
-
- ++iterator_;
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
deleted file mode 100644
index 98ee2dd53..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader.h
+++ /dev/null
@@ -1,325 +0,0 @@
-// -*- mode: c++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// stabs_reader.h: Define StabsReader, a parser for STABS debugging
-// information. A description of the STABS debugging format can be
-// found at:
-//
-// http://sourceware.org/gdb/current/onlinedocs/stabs_toc.html
-//
-// The comments here assume you understand the format.
-//
-// This parser can handle big-endian and little-endian data, and the symbol
-// values may be either 32 or 64 bits long. It handles both STABS in
-// sections (as used on Linux) and STABS appearing directly in an
-// a.out-like symbol table (as used in Darwin OS X Mach-O files).
-
-#ifndef COMMON_STABS_READER_H__
-#define COMMON_STABS_READER_H__
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifdef HAVE_MACH_O_NLIST_H
-#include <mach-o/nlist.h>
-#elif defined(HAVE_A_OUT_H)
-#include <a.out.h>
-#endif
-
-#include <string>
-#include <vector>
-
-#include "common/byte_cursor.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-class StabsHandler;
-
-class StabsReader {
- public:
- // Create a reader for the STABS debug information whose .stab section is
- // being traversed by ITERATOR, and whose .stabstr section is referred to
- // by STRINGS. The reader will call the member functions of HANDLER to
- // report the information it finds, when the reader's 'Process' member
- // function is called.
- //
- // BIG_ENDIAN should be true if the entries in the .stab section are in
- // big-endian form, or false if they are in little-endian form.
- //
- // VALUE_SIZE should be either 4 or 8, indicating the size of the 'value'
- // field in each entry in bytes.
- //
- // UNITIZED should be true if the STABS data is stored in units with
- // N_UNDF headers. This is usually the case for STABS stored in sections,
- // like .stab/.stabstr, and usually not the case for STABS stored in the
- // actual symbol table; UNITIZED should be true when parsing Linux stabs,
- // false when parsing Mac OS X STABS. For details, see:
- // http://sourceware.org/gdb/current/onlinedocs/stabs/Stab-Section-Basics.html
- //
- // Note that, in ELF, the .stabstr section should be found using the
- // 'sh_link' field of the .stab section header, not by name.
- StabsReader(const uint8_t *stab, size_t stab_size,
- const uint8_t *stabstr, size_t stabstr_size,
- bool big_endian, size_t value_size, bool unitized,
- StabsHandler *handler);
-
- // Process the STABS data, calling the handler's member functions to
- // report what we find. While the handler functions return true,
- // continue to process until we reach the end of the section. If we
- // processed the entire section and all handlers returned true,
- // return true. If any handler returned false, return false.
- //
- // This is only meant to be called once per StabsReader instance;
- // resuming a prior processing pass that stopped abruptly isn't supported.
- bool Process();
-
- private:
-
- // An class for walking arrays of STABS entries. This isolates the main
- // STABS reader from the exact format (size; endianness) of the entries
- // themselves.
- class EntryIterator {
- public:
- // The contents of a STABS entry, adjusted for the host's endianness,
- // word size, 'struct nlist' layout, and so on.
- struct Entry {
- // True if this iterator has reached the end of the entry array. When
- // this is set, the other members of this structure are not valid.
- bool at_end;
-
- // The number of this entry within the list.
- size_t index;
-
- // The current entry's name offset. This is the offset within the
- // current compilation unit's strings, as establish by the N_UNDF entries.
- size_t name_offset;
-
- // The current entry's type, 'other' field, descriptor, and value.
- unsigned char type;
- unsigned char other;
- short descriptor;
- uint64_t value;
- };
-
- // Create a EntryIterator walking the entries in BUFFER. Treat the
- // entries as big-endian if BIG_ENDIAN is true, as little-endian
- // otherwise. Assume each entry has a 'value' field whose size is
- // VALUE_SIZE.
- //
- // This would not be terribly clean to extend to other format variations,
- // but it's enough to handle Linux and Mac, and we'd like STABS to die
- // anyway.
- //
- // For the record: on Linux, STABS entry values are always 32 bits,
- // regardless of the architecture address size (don't ask me why); on
- // Mac, they are 32 or 64 bits long. Oddly, the section header's entry
- // size for a Linux ELF .stab section varies according to the ELF class
- // from 12 to 20 even as the actual entries remain unchanged.
- EntryIterator(const ByteBuffer *buffer, bool big_endian, size_t value_size);
-
- // Move to the next entry. This function's behavior is undefined if
- // at_end() is true when it is called.
- EntryIterator &operator++() { Fetch(); entry_.index++; return *this; }
-
- // Dereferencing this iterator produces a reference to an Entry structure
- // that holds the current entry's values. The entry is owned by this
- // EntryIterator, and will be invalidated at the next call to operator++.
- const Entry &operator*() const { return entry_; }
- const Entry *operator->() const { return &entry_; }
-
- private:
- // Read the STABS entry at cursor_, and set entry_ appropriately.
- void Fetch();
-
- // The size of entries' value field, in bytes.
- size_t value_size_;
-
- // A byte cursor traversing buffer_.
- ByteCursor cursor_;
-
- // Values for the entry this iterator refers to.
- Entry entry_;
- };
-
- // A source line, saved to be reported later.
- struct Line {
- uint64_t address;
- const char *filename;
- int number;
- };
-
- // Return the name of the current symbol.
- const char *SymbolString();
-
- // Process a compilation unit starting at symbol_. Return true
- // to continue processing, or false to abort.
- bool ProcessCompilationUnit();
-
- // Process a function in current_source_file_ starting at symbol_.
- // Return true to continue processing, or false to abort.
- bool ProcessFunction();
-
- // Process an exported function symbol.
- // Return true to continue processing, or false to abort.
- bool ProcessExtern();
-
- // The STABS entries being parsed.
- ByteBuffer entries_;
-
- // The string section to which the entries refer.
- ByteBuffer strings_;
-
- // The iterator walking the STABS entries.
- EntryIterator iterator_;
-
- // True if the data is "unitized"; see the explanation in the comment for
- // StabsReader::StabsReader.
- bool unitized_;
-
- StabsHandler *handler_;
-
- // The offset of the current compilation unit's strings within stabstr_.
- size_t string_offset_;
-
- // The value string_offset_ should have for the next compilation unit,
- // as established by N_UNDF entries.
- size_t next_cu_string_offset_;
-
- // The current source file name.
- const char *current_source_file_;
-
- // Mac OS X STABS place SLINE records before functions; we accumulate a
- // vector of these until we see the FUN record, and then report them
- // after the StartFunction call.
- std::vector<Line> queued_lines_;
-};
-
-// Consumer-provided callback structure for the STABS reader. Clients
-// of the STABS reader provide an instance of this structure. The
-// reader then invokes the member functions of that instance to report
-// the information it finds.
-//
-// The default definitions of the member functions do nothing, and return
-// true so processing will continue.
-class StabsHandler {
- public:
- StabsHandler() { }
- virtual ~StabsHandler() { }
-
- // Some general notes about the handler callback functions:
-
- // Processing proceeds until the end of the .stabs section, or until
- // one of these functions returns false.
-
- // The addresses given are as reported in the STABS info, without
- // regard for whether the module may be loaded at different
- // addresses at different times (a shared library, say). When
- // processing STABS from an ELF shared library, the addresses given
- // all assume the library is loaded at its nominal load address.
- // They are *not* offsets from the nominal load address. If you
- // want offsets, you must subtract off the library's nominal load
- // address.
-
- // The arguments to these functions named FILENAME are all
- // references to strings stored in the .stabstr section. Because
- // both the Linux and Solaris linkers factor out duplicate strings
- // from the .stabstr section, the consumer can assume that if two
- // FILENAME values are different addresses, they represent different
- // file names.
- //
- // Thus, it's safe to use (say) std::map<char *, ...>, which does
- // string address comparisons, not string content comparisons.
- // Since all the strings are in same array of characters --- the
- // .stabstr section --- comparing their addresses produces
- // predictable, if not lexicographically meaningful, results.
-
- // Begin processing a compilation unit whose main source file is
- // named FILENAME, and whose base address is ADDRESS. If
- // BUILD_DIRECTORY is non-NULL, it is the name of the build
- // directory in which the compilation occurred.
- virtual bool StartCompilationUnit(const char *filename, uint64_t address,
- const char *build_directory) {
- return true;
- }
-
- // Finish processing the compilation unit. If ADDRESS is non-zero,
- // it is the ending address of the compilation unit. If ADDRESS is
- // zero, then the compilation unit's ending address is not
- // available, and the consumer must infer it by other means.
- virtual bool EndCompilationUnit(uint64_t address) { return true; }
-
- // Begin processing a function named NAME, whose starting address is
- // ADDRESS. This function belongs to the compilation unit that was
- // most recently started but not ended.
- //
- // Note that, unlike filenames, NAME is not a pointer into the
- // .stabstr section; this is because the name as it appears in the
- // STABS data is followed by type information. The value passed to
- // StartFunction is the function name alone.
- //
- // In languages that use name mangling, like C++, NAME is mangled.
- virtual bool StartFunction(const string &name, uint64_t address) {
- return true;
- }
-
- // Finish processing the function. If ADDRESS is non-zero, it is
- // the ending address for the function. If ADDRESS is zero, then
- // the function's ending address is not available, and the consumer
- // must infer it by other means.
- virtual bool EndFunction(uint64_t address) { return true; }
-
- // Report that the code at ADDRESS is attributable to line NUMBER of
- // the source file named FILENAME. The caller must infer the ending
- // address of the line.
- virtual bool Line(uint64_t address, const char *filename, int number) {
- return true;
- }
-
- // Report that an exported function NAME is present at ADDRESS.
- // The size of the function is unknown.
- virtual bool Extern(const string &name, uint64_t address) {
- return true;
- }
-
- // Report a warning. FORMAT is a printf-like format string,
- // specifying how to format the subsequent arguments.
- virtual void Warning(const char *format, ...) = 0;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_STABS_READER_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc
deleted file mode 100644
index a84da1c4c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_reader_unittest.cc
+++ /dev/null
@@ -1,611 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// stabs_reader_unittest.cc: Unit tests for google_breakpad::StabsReader.
-
-#include <assert.h>
-#include <errno.h>
-#include <stab.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <fstream>
-#include <iomanip>
-#include <iostream>
-#include <map>
-#include <sstream>
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/stabs_reader.h"
-#include "common/test_assembler.h"
-#include "common/using_std_string.h"
-
-using ::testing::Eq;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::StrEq;
-using ::testing::Test;
-using ::testing::_;
-using google_breakpad::StabsHandler;
-using google_breakpad::StabsReader;
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::Section;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using std::map;
-
-namespace {
-
-// A StringAssembler is a class for generating .stabstr sections to present
-// as input to the STABS parser.
-class StringAssembler: public Section {
- public:
- StringAssembler() : in_cu_(false) { StartCU(); }
-
- // Add the string S to this StringAssembler, and return the string's
- // offset within this compilation unit's strings. If S has been added
- // already, this returns the offset of its first instance.
- size_t Add(const string &s) {
- map<string, size_t>::iterator it = added_.find(s);
- if (it != added_.end())
- return it->second;
- size_t offset = Size() - cu_start_;
- AppendCString(s);
- added_[s] = offset;
- return offset;
- }
-
- // Start a fresh compilation unit string collection.
- void StartCU() {
- // Ignore duplicate calls to StartCU. Our test data don't always call
- // StartCU at all, meaning that our constructor has to take care of it,
- // meaning that tests that *do* call StartCU call it twice at the
- // beginning. This is not worth smoothing out.
- if (in_cu_) return;
-
- added_.clear();
- cu_start_ = Size();
-
- // Each compilation unit's strings start with an empty string.
- AppendCString("");
- added_[""] = 0;
-
- in_cu_ = true;
- }
-
- // Finish off the current CU's strings.
- size_t EndCU() {
- assert(in_cu_);
- in_cu_ = false;
- return Size() - cu_start_;
- }
-
- private:
- // The offset of the start of this compilation unit's strings.
- size_t cu_start_;
-
- // True if we're in a CU.
- bool in_cu_;
-
- // A map from the strings that have been added to this section to
- // their starting indices within their compilation unit.
- map<string, size_t> added_;
-};
-
-// A StabsAssembler is a class for generating .stab sections to present as
-// test input for the STABS parser.
-class StabsAssembler: public Section {
- public:
- // Create a StabsAssembler that uses StringAssembler for its strings.
- StabsAssembler(StringAssembler *string_assembler)
- : Section(string_assembler->endianness()),
- string_assembler_(string_assembler),
- value_size_(0),
- entry_count_(0),
- cu_header_(NULL) { }
- ~StabsAssembler() { assert(!cu_header_); }
-
- // Accessor and setter for value_size_.
- size_t value_size() const { return value_size_; }
- StabsAssembler &set_value_size(size_t value_size) {
- value_size_ = value_size;
- return *this;
- }
-
- // Append a STAB entry to the end of this section with the given
- // characteristics. NAME is the offset of this entry's name string within
- // its compilation unit's portion of the .stabstr section; this can be a
- // value generated by a StringAssembler. Return a reference to this
- // StabsAssembler.
- StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor,
- Label value, Label name) {
- D32(name);
- D8(type);
- D8(other);
- D16(descriptor);
- Append(endianness(), value_size_, value);
- entry_count_++;
- return *this;
- }
-
- // As above, but automatically add NAME to our StringAssembler.
- StabsAssembler &Stab(uint8_t type, uint8_t other, Label descriptor,
- Label value, const string &name) {
- return Stab(type, other, descriptor, value, string_assembler_->Add(name));
- }
-
- // Start a compilation unit named NAME, with an N_UNDF symbol to start
- // it, and its own portion of the string section. Return a reference to
- // this StabsAssembler.
- StabsAssembler &StartCU(const string &name) {
- assert(!cu_header_);
- cu_header_ = new CUHeader;
- string_assembler_->StartCU();
- entry_count_ = 0;
- return Stab(N_UNDF, 0,
- cu_header_->final_entry_count,
- cu_header_->final_string_size,
- string_assembler_->Add(name));
- }
-
- // Close off the current compilation unit. Return a reference to this
- // StabsAssembler.
- StabsAssembler &EndCU() {
- assert(cu_header_);
- cu_header_->final_entry_count = entry_count_;
- cu_header_->final_string_size = string_assembler_->EndCU();
- delete cu_header_;
- cu_header_ = NULL;
- return *this;
- }
-
- private:
- // Data used in a compilation unit header STAB that we won't know until
- // we've finished the compilation unit.
- struct CUHeader {
- // The final number of entries this compilation unit will hold.
- Label final_entry_count;
-
- // The final size of this compilation unit's strings.
- Label final_string_size;
- };
-
- // The strings for our STABS entries.
- StringAssembler *string_assembler_;
-
- // The size of the 'value' field of stabs entries in this section.
- size_t value_size_;
-
- // The number of entries in this compilation unit so far.
- size_t entry_count_;
-
- // Header labels for this compilation unit, if we've started one but not
- // finished it.
- CUHeader *cu_header_;
-};
-
-class MockStabsReaderHandler: public StabsHandler {
- public:
- MOCK_METHOD3(StartCompilationUnit,
- bool(const char *, uint64_t, const char *));
- MOCK_METHOD1(EndCompilationUnit, bool(uint64_t));
- MOCK_METHOD2(StartFunction, bool(const string &, uint64_t));
- MOCK_METHOD1(EndFunction, bool(uint64_t));
- MOCK_METHOD3(Line, bool(uint64_t, const char *, int));
- MOCK_METHOD2(Extern, bool(const string &, uint64_t));
- void Warning(const char *format, ...) { MockWarning(format); }
- MOCK_METHOD1(MockWarning, void(const char *));
-};
-
-struct StabsFixture {
- StabsFixture() : stabs(&strings), unitized(true) { }
-
- // Create a StabsReader to parse the mock stabs data in stabs and
- // strings, and pass the parsed information to mock_handler. Use the
- // endianness and value size of stabs to parse the data. If all goes
- // well, return the result of calling the reader's Process member
- // function. Otherwise, return false.
- bool ApplyHandlerToMockStabsData() {
- string stabs_contents, stabstr_contents;
- if (!stabs.GetContents(&stabs_contents) ||
- !strings.GetContents(&stabstr_contents))
- return false;
-
- // Run the parser on the test input, passing whatever we find to HANDLER.
- StabsReader reader(
- reinterpret_cast<const uint8_t *>(stabs_contents.data()),
- stabs_contents.size(),
- reinterpret_cast<const uint8_t *>(stabstr_contents.data()),
- stabstr_contents.size(),
- stabs.endianness() == kBigEndian, stabs.value_size(), unitized,
- &mock_handler);
- return reader.Process();
- }
-
- StringAssembler strings;
- StabsAssembler stabs;
- bool unitized;
- MockStabsReaderHandler mock_handler;
-};
-
-class Stabs: public StabsFixture, public Test { };
-
-TEST_F(Stabs, MockStabsInput) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(4);
- stabs
- .Stab(N_SO, 149, 40232, 0x18a2a72bU, "builddir/")
- .Stab(N_FUN, 83, 50010, 0x91a5353fU,
- "not the SO with source file name we expected ")
- .Stab(N_SO, 165, 24791, 0xfe69d23cU, "")
- .Stab(N_SO, 184, 34178, 0xca4d883aU, "builddir1/")
- .Stab(N_SO, 83, 40859, 0xd2fe5df3U, "file1.c")
- .Stab(N_LSYM, 147, 39565, 0x60d4bb8aU, "not the FUN we're looking for")
- .Stab(N_FUN, 120, 50271, 0xa049f4b1U, "fun1")
- .Stab(N_BINCL, 150, 15694, 0xef65c659U,
- "something to ignore in a FUN body")
- .Stab(N_SLINE, 147, 4967, 0xd904b3f, "")
- .Stab(N_SOL, 177, 56135, 0xbd97b1dcU, "header.h")
- .Stab(N_SLINE, 130, 24610, 0x90f145b, "")
- .Stab(N_FUN, 45, 32441, 0xbf27cf93U,
- "fun2:some stabs type info here:to trim from the name")
- .Stab(N_SLINE, 138, 39002, 0x8148b87, "")
- .Stab(N_SOL, 60, 49318, 0x1d06e025U, "file1.c")
- .Stab(N_SLINE, 29, 52163, 0x6eebbb7, "")
- .Stab(N_SO, 167, 4647, 0xd04b7448U, "")
- .Stab(N_LSYM, 58, 37837, 0xe6b14d37U, "")
- .Stab(N_SO, 152, 7810, 0x11759f10U, "file3.c")
- .Stab(N_SO, 218, 12447, 0x11cfe4b5U, "");
-
- {
- InSequence s;
-
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("file1.c"), 0xd2fe5df3U,
- StrEq("builddir1/")))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartFunction(StrEq("fun1"), 0xa049f4b1U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0xa049f4b1U + 0xd904b3f, StrEq("file1.c"), 4967))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0xa049f4b1U + 0x90f145b, StrEq("header.h"), 24610))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xbf27cf93U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartFunction(StrEq("fun2"), 0xbf27cf93U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0xbf27cf93U + 0x8148b87, StrEq("header.h"), 39002))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0xbf27cf93U + 0x6eebbb7, StrEq("file1.c"), 52163))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xd04b7448U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0xd04b7448U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartCompilationUnit(StrEq("file3.c"),
- 0x11759f10U, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0x11cfe4b5U))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, AbruptCU) {
- stabs.set_endianness(kBigEndian);
- stabs.set_value_size(4);
- stabs.Stab(N_SO, 177, 23446, 0xbf10d5e4, "file2-1.c");
-
- {
- InSequence s;
-
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("file2-1.c"), 0xbf10d5e4, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, AbruptFunction) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(8);
- stabs
- .Stab(N_SO, 218, 26631, 0xb83ddf10U, "file3-1.c")
- .Stab(N_FUN, 113, 24765, 0xbbd4a145U, "fun3_1");
-
- {
- InSequence s;
-
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("file3-1.c"), 0xb83ddf10U, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartFunction(StrEq("fun3_1"), 0xbbd4a145U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, NoCU) {
- stabs.set_endianness(kBigEndian);
- stabs.set_value_size(8);
- stabs.Stab(N_SO, 161, 25673, 0x8f676e7bU, "build-directory/");
-
- EXPECT_CALL(mock_handler, StartCompilationUnit(_, _, _))
- .Times(0);
- EXPECT_CALL(mock_handler, StartFunction(_, _))
- .Times(0);
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, NoCUEnd) {
- stabs.set_endianness(kBigEndian);
- stabs.set_value_size(8);
- stabs
- .Stab(N_SO, 116, 58280, 0x2f7493c9U, "file5-1.c")
- .Stab(N_SO, 224, 23057, 0xf9f1d50fU, "file5-2.c");
-
- {
- InSequence s;
-
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("file5-1.c"), 0x2f7493c9U, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("file5-2.c"), 0xf9f1d50fU, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-// On systems that store STABS in sections, string offsets are relative to
-// the beginning of that compilation unit's strings, marked with N_UNDF
-// symbols; see the comments for StabsReader::StabsReader.
-TEST_F(Stabs, Unitized) {
- stabs.set_endianness(kBigEndian);
- stabs.set_value_size(4);
- stabs
- .StartCU("antimony")
- .Stab(N_SO, 49, 26043, 0x7e259f1aU, "antimony")
- .Stab(N_FUN, 101, 63253, 0x7fbcccaeU, "arsenic")
- .Stab(N_SO, 124, 37175, 0x80b0014cU, "")
- .EndCU()
- .StartCU("aluminum")
- .Stab(N_SO, 72, 23084, 0x86756839U, "aluminum")
- .Stab(N_FUN, 59, 3305, 0xa8e120b0U, "selenium")
- .Stab(N_SO, 178, 56949, 0xbffff983U, "")
- .EndCU();
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("antimony"), 0x7e259f1aU, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartFunction(Eq("arsenic"), 0x7fbcccaeU))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0x80b0014cU))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0x80b0014cU))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("aluminum"), 0x86756839U, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, StartFunction(Eq("selenium"), 0xa8e120b0U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xbffff983U))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0xbffff983U))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-// On systems that store STABS entries in the real symbol table, the N_UNDF
-// entries have no special meaning, and shouldn't mess up the string
-// indices.
-TEST_F(Stabs, NonUnitized) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(4);
- unitized = false;
- stabs
- .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "")
- .Stab(N_UNDF, 21, 11551, 0x9bad2b2e, "")
- .Stab(N_SO, 71, 45139, 0x11a97352, "Tanzania")
- .Stab(N_SO, 221, 41976, 0x21a97352, "");
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("Tanzania"),
- 0x11a97352, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0x21a97352))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, FunctionEnd) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(8);
- stabs
- .Stab(N_SO, 102, 62362, 0x52a830d644cd6942ULL, "compilation unit")
- // This function is terminated by the start of the next function.
- .Stab(N_FUN, 216, 38405, 0xbb5ab70ecdd23bfeULL, "function 1")
- // This function is terminated by an explicit end-of-function stab,
- // whose value is a size in bytes.
- .Stab(N_FUN, 240, 10973, 0xc954de9b8fb3e5e2ULL, "function 2")
- .Stab(N_FUN, 14, 36749, 0xc1ab, "")
- // This function is terminated by the end of the compilation unit.
- .Stab(N_FUN, 143, 64514, 0xdff98c9a35386e1fULL, "function 3")
- .Stab(N_SO, 164, 60142, 0xfdacb856e78bbf57ULL, "");
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("compilation unit"),
- 0x52a830d644cd6942ULL, NULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartFunction(Eq("function 1"), 0xbb5ab70ecdd23bfeULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartFunction(Eq("function 2"), 0xc954de9b8fb3e5e2ULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xc954de9b8fb3e5e2ULL + 0xc1ab))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartFunction(Eq("function 3"), 0xdff98c9a35386e1fULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xfdacb856e78bbf57ULL))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0xfdacb856e78bbf57ULL))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-// On Mac OS X, SLINE records can appear before the FUN stab to which they
-// belong, and their values are absolute addresses, not offsets.
-TEST_F(Stabs, LeadingLine) {
- stabs.set_endianness(kBigEndian);
- stabs.set_value_size(4);
- stabs
- .Stab(N_SO, 179, 27357, 0x8adabc15, "build directory/")
- .Stab(N_SO, 52, 53058, 0x4c7e3bf4, "compilation unit")
- .Stab(N_SOL, 165, 12086, 0x6a797ca3, "source file name")
- .Stab(N_SLINE, 229, 20015, 0x4cb3d7e0, "")
- .Stab(N_SLINE, 89, 43802, 0x4cba8b88, "")
- .Stab(N_FUN, 251, 51639, 0xce1b98fa, "rutabaga")
- .Stab(N_FUN, 218, 16113, 0x5798, "")
- .Stab(N_SO, 52, 53058, 0xd4af4415, "");
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- StartCompilationUnit(StrEq("compilation unit"),
- 0x4c7e3bf4, StrEq("build directory/")))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- StartFunction(Eq("rutabaga"), 0xce1b98fa))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0x4cb3d7e0, StrEq("source file name"), 20015))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Line(0x4cba8b88, StrEq("source file name"), 43802))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndFunction(0xce1b98fa + 0x5798))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler, EndCompilationUnit(0xd4af4415))
- .WillOnce(Return(true));
- }
-
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-
-#if defined(HAVE_MACH_O_NLIST_H)
-// These tests have no meaning on non-Mach-O-based systems, as
-// only Mach-O uses N_SECT to represent public symbols.
-TEST_F(Stabs, OnePublicSymbol) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(4);
-
- const uint32_t kExpectedAddress = 0x9000;
- const string kExpectedFunctionName("public_function");
- stabs
- .Stab(N_SECT, 1, 0, kExpectedAddress, kExpectedFunctionName);
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- Extern(StrEq(kExpectedFunctionName),
- kExpectedAddress))
- .WillOnce(Return(true));
- }
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-TEST_F(Stabs, TwoPublicSymbols) {
- stabs.set_endianness(kLittleEndian);
- stabs.set_value_size(4);
-
- const uint32_t kExpectedAddress1 = 0xB0B0B0B0;
- const string kExpectedFunctionName1("public_function");
- const uint32_t kExpectedAddress2 = 0xF0F0F0F0;
- const string kExpectedFunctionName2("something else");
- stabs
- .Stab(N_SECT, 1, 0, kExpectedAddress1, kExpectedFunctionName1)
- .Stab(N_SECT, 1, 0, kExpectedAddress2, kExpectedFunctionName2);
-
- {
- InSequence s;
- EXPECT_CALL(mock_handler,
- Extern(StrEq(kExpectedFunctionName1),
- kExpectedAddress1))
- .WillOnce(Return(true));
- EXPECT_CALL(mock_handler,
- Extern(StrEq(kExpectedFunctionName2),
- kExpectedAddress2))
- .WillOnce(Return(true));
- }
- ASSERT_TRUE(ApplyHandlerToMockStabsData());
-}
-
-#endif
-
-} // anonymous namespace
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.cc
deleted file mode 100644
index 0a83cf21c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.cc
+++ /dev/null
@@ -1,197 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_stabs.cc --- implement the StabsToModule class.
-
-#include <assert.h>
-#include <cxxabi.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <algorithm>
-
-#include "common/stabs_to_module.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-// Demangle using abi call.
-// Older GCC may not support it.
-static string Demangle(const string &mangled) {
- int status = 0;
- char *demangled = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status);
- if (status == 0 && demangled != NULL) {
- string str(demangled);
- free(demangled);
- return str;
- }
- return string(mangled);
-}
-
-StabsToModule::~StabsToModule() {
- // Free any functions we've accumulated but not added to the module.
- for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
- func_it != functions_.end(); func_it++)
- delete *func_it;
- // Free any function that we're currently within.
- delete current_function_;
-}
-
-bool StabsToModule::StartCompilationUnit(const char *name, uint64_t address,
- const char *build_directory) {
- assert(!in_compilation_unit_);
- in_compilation_unit_ = true;
- current_source_file_name_ = name;
- current_source_file_ = module_->FindFile(name);
- comp_unit_base_address_ = address;
- boundaries_.push_back(static_cast<Module::Address>(address));
- return true;
-}
-
-bool StabsToModule::EndCompilationUnit(uint64_t address) {
- assert(in_compilation_unit_);
- in_compilation_unit_ = false;
- comp_unit_base_address_ = 0;
- current_source_file_ = NULL;
- current_source_file_name_ = NULL;
- if (address)
- boundaries_.push_back(static_cast<Module::Address>(address));
- return true;
-}
-
-bool StabsToModule::StartFunction(const string &name,
- uint64_t address) {
- assert(!current_function_);
- Module::Function *f = new Module::Function(Demangle(name), address);
- f->size = 0; // We compute this in StabsToModule::Finalize().
- f->parameter_size = 0; // We don't provide this information.
- current_function_ = f;
- boundaries_.push_back(static_cast<Module::Address>(address));
- return true;
-}
-
-bool StabsToModule::EndFunction(uint64_t address) {
- assert(current_function_);
- // Functions in this compilation unit should have address bigger
- // than the compilation unit's starting address. There may be a lot
- // of duplicated entries for functions in the STABS data. We will
- // count on the Module to remove the duplicates.
- if (current_function_->address >= comp_unit_base_address_)
- functions_.push_back(current_function_);
- else
- delete current_function_;
- current_function_ = NULL;
- if (address)
- boundaries_.push_back(static_cast<Module::Address>(address));
- return true;
-}
-
-bool StabsToModule::Line(uint64_t address, const char *name, int number) {
- assert(current_function_);
- assert(current_source_file_);
- if (name != current_source_file_name_) {
- current_source_file_ = module_->FindFile(name);
- current_source_file_name_ = name;
- }
- Module::Line line;
- line.address = address;
- line.size = 0; // We compute this in StabsToModule::Finalize().
- line.file = current_source_file_;
- line.number = number;
- current_function_->lines.push_back(line);
- return true;
-}
-
-bool StabsToModule::Extern(const string &name, uint64_t address) {
- Module::Extern *ext = new Module::Extern(address);
- // Older libstdc++ demangle implementations can crash on unexpected
- // input, so be careful about what gets passed in.
- if (name.compare(0, 3, "__Z") == 0) {
- ext->name = Demangle(name.substr(1));
- } else if (name[0] == '_') {
- ext->name = name.substr(1);
- } else {
- ext->name = name;
- }
- module_->AddExtern(ext);
- return true;
-}
-
-void StabsToModule::Warning(const char *format, ...) {
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
-}
-
-void StabsToModule::Finalize() {
- // Sort our boundary list, so we can search it quickly.
- sort(boundaries_.begin(), boundaries_.end());
- // Sort all functions by address, just for neatness.
- sort(functions_.begin(), functions_.end(),
- Module::Function::CompareByAddress);
-
- for (vector<Module::Function *>::const_iterator func_it = functions_.begin();
- func_it != functions_.end();
- func_it++) {
- Module::Function *f = *func_it;
- // Compute the function f's size.
- vector<Module::Address>::const_iterator boundary
- = std::upper_bound(boundaries_.begin(), boundaries_.end(), f->address);
- if (boundary != boundaries_.end())
- f->size = *boundary - f->address;
- else
- // If this is the last function in the module, and the STABS
- // reader was unable to give us its ending address, then assign
- // it a bogus, very large value. This will happen at most once
- // per module: since we've added all functions' addresses to the
- // boundary table, only one can be the last.
- f->size = kFallbackSize;
-
- // Compute sizes for each of the function f's lines --- if it has any.
- if (!f->lines.empty()) {
- stable_sort(f->lines.begin(), f->lines.end(),
- Module::Line::CompareByAddress);
- vector<Module::Line>::iterator last_line = f->lines.end() - 1;
- for (vector<Module::Line>::iterator line_it = f->lines.begin();
- line_it != last_line; line_it++)
- line_it[0].size = line_it[1].address - line_it[0].address;
- // Compute the size of the last line from f's end address.
- last_line->size = (f->address + f->size) - last_line->address;
- }
- }
- // Now that everything has a size, add our functions to the module, and
- // dispose of our private list.
- module_->AddFunctions(functions_.begin(), functions_.end());
- functions_.clear();
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.h b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.h
deleted file mode 100644
index 5e04fa792..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_stabs.h: Define the StabsToModule class, which receives
-// STABS debugging information from a parser and adds it to a Breakpad
-// symbol file.
-
-#ifndef BREAKPAD_COMMON_STABS_TO_MODULE_H_
-#define BREAKPAD_COMMON_STABS_TO_MODULE_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "common/module.h"
-#include "common/stabs_reader.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using std::vector;
-
-// A StabsToModule is a handler that receives parsed STABS debugging
-// information from a StabsReader, and uses that to populate
-// a Module. (All classes are in the google_breakpad namespace.) A
-// Module represents the contents of a Breakpad symbol file, and knows
-// how to write itself out as such. A StabsToModule thus acts as
-// the bridge between STABS and Breakpad data.
-// When processing Darwin Mach-O files, this also receives public linker
-// symbols, like those found in system libraries.
-class StabsToModule: public google_breakpad::StabsHandler {
- public:
- // Receive parsed debugging information from a StabsReader, and
- // store it all in MODULE.
- StabsToModule(Module *module) :
- module_(module),
- in_compilation_unit_(false),
- comp_unit_base_address_(0),
- current_function_(NULL),
- current_source_file_(NULL),
- current_source_file_name_(NULL) { }
- ~StabsToModule();
-
- // The standard StabsHandler virtual member functions.
- bool StartCompilationUnit(const char *name, uint64_t address,
- const char *build_directory);
- bool EndCompilationUnit(uint64_t address);
- bool StartFunction(const string &name, uint64_t address);
- bool EndFunction(uint64_t address);
- bool Line(uint64_t address, const char *name, int number);
- bool Extern(const string &name, uint64_t address);
- void Warning(const char *format, ...);
-
- // Do any final processing necessary to make module_ contain all the
- // data provided by the STABS reader.
- //
- // Because STABS does not provide reliable size information for
- // functions and lines, we need to make a pass over the data after
- // processing all the STABS to compute those sizes. We take care of
- // that here.
- void Finalize();
-
- private:
-
- // An arbitrary, but very large, size to use for functions whose
- // size we can't compute properly.
- static const uint64_t kFallbackSize = 0x10000000;
-
- // The module we're contributing debugging info to.
- Module *module_;
-
- // The functions we've generated so far. We don't add these to
- // module_ as we parse them. Instead, we wait until we've computed
- // their ending address, and their lines' ending addresses.
- //
- // We could just stick them in module_ from the outset, but if
- // module_ already contains data gathered from other debugging
- // formats, that would complicate the size computation.
- vector<Module::Function *> functions_;
-
- // Boundary addresses. STABS doesn't necessarily supply sizes for
- // functions and lines, so we need to compute them ourselves by
- // finding the next object.
- vector<Module::Address> boundaries_;
-
- // True if we are currently within a compilation unit: we have gotten a
- // StartCompilationUnit call, but no matching EndCompilationUnit call
- // yet. We use this for sanity checks.
- bool in_compilation_unit_;
-
- // The base address of the current compilation unit. We use this to
- // recognize functions we should omit from the symbol file. (If you
- // know the details of why we omit these, please patch this
- // comment.)
- Module::Address comp_unit_base_address_;
-
- // The function we're currently contributing lines to.
- Module::Function *current_function_;
-
- // The last Module::File we got a line number in.
- Module::File *current_source_file_;
-
- // The pointer in the .stabstr section of the name that
- // current_source_file_ is built from. This allows us to quickly
- // recognize when the current line is in the same file as the
- // previous one (which it usually is).
- const char *current_source_file_name_;
-};
-
-} // namespace google_breakpad
-
-#endif // BREAKPAD_COMMON_STABS_TO_MODULE_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc
deleted file mode 100644
index d445d1d64..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stabs_to_module_unittest.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// dump_stabs_unittest.cc: Unit tests for StabsToModule.
-
-#include <vector>
-
-#include "breakpad_googletest_includes.h"
-#include "common/stabs_to_module.h"
-
-using google_breakpad::Module;
-using google_breakpad::StabsToModule;
-using std::vector;
-
-TEST(StabsToModule, SimpleCU) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // Feed in a simple compilation unit that defines a function with
- // one line.
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0x9f4d1271e50db93bLL,
- "build-directory"));
- EXPECT_TRUE(h.StartFunction("function", 0xfde4abbed390c394LL));
- EXPECT_TRUE(h.Line(0xfde4abbed390c394LL, "source-file-name", 174823314));
- EXPECT_TRUE(h.EndFunction(0xfde4abbed390c3a4LL));
- EXPECT_TRUE(h.EndCompilationUnit(0xfee4abbed390c3a4LL));
- h.Finalize();
-
- // Now check to see what has been added to the Module.
- Module::File *file = m.FindExistingFile("source-file-name");
- ASSERT_TRUE(file != NULL);
-
- vector<Module::Function *> functions;
- m.GetFunctions(&functions, functions.end());
- ASSERT_EQ((size_t) 1, functions.size());
- Module::Function *function = functions[0];
- EXPECT_STREQ("function", function->name.c_str());
- EXPECT_EQ(0xfde4abbed390c394LL, function->address);
- EXPECT_EQ(0x10U, function->size);
- EXPECT_EQ(0U, function->parameter_size);
- ASSERT_EQ((size_t) 1, function->lines.size());
- Module::Line *line = &function->lines[0];
- EXPECT_EQ(0xfde4abbed390c394LL, line->address);
- EXPECT_EQ(0x10U, line->size); // derived from EndFunction
- EXPECT_TRUE(line->file == file);
- EXPECT_EQ(174823314, line->number);
-}
-
-#ifdef __GNUC__
-// Function name mangling can vary by compiler, so only run mangled-name
-// tests on GCC for simplicity's sake.
-TEST(StabsToModule, Externs) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // Feed in a few Extern symbols.
- EXPECT_TRUE(h.Extern("_foo", 0xffff));
- EXPECT_TRUE(h.Extern("__Z21dyldGlobalLockAcquirev", 0xaaaa));
- EXPECT_TRUE(h.Extern("_MorphTableGetNextMorphChain", 0x1111));
- h.Finalize();
-
- // Now check to see what has been added to the Module.
- vector<Module::Extern *> externs;
- m.GetExterns(&externs, externs.end());
- ASSERT_EQ((size_t) 3, externs.size());
- Module::Extern *extern1 = externs[0];
- EXPECT_STREQ("MorphTableGetNextMorphChain", extern1->name.c_str());
- EXPECT_EQ((Module::Address)0x1111, extern1->address);
- Module::Extern *extern2 = externs[1];
- EXPECT_STREQ("dyldGlobalLockAcquire()", extern2->name.c_str());
- EXPECT_EQ((Module::Address)0xaaaa, extern2->address);
- Module::Extern *extern3 = externs[2];
- EXPECT_STREQ("foo", extern3->name.c_str());
- EXPECT_EQ((Module::Address)0xffff, extern3->address);
-}
-#endif // __GNUC__
-
-TEST(StabsToModule, DuplicateFunctionNames) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // Compilation unit with one function, mangled name.
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda36ecf7f46cLL,
- "build-directory"));
- EXPECT_TRUE(h.StartFunction("funcfoo",
- 0xf2cfda36ecf7f46dLL));
- EXPECT_TRUE(h.EndFunction(0));
- EXPECT_TRUE(h.StartFunction("funcfoo",
- 0xf2cfda36ecf7f46dLL));
- EXPECT_TRUE(h.EndFunction(0));
- EXPECT_TRUE(h.EndCompilationUnit(0));
-
- h.Finalize();
-
- // Now check to see what has been added to the Module.
- Module::File *file = m.FindExistingFile("compilation-unit");
- ASSERT_TRUE(file != NULL);
-
- vector<Module::Function *> functions;
- m.GetFunctions(&functions, functions.end());
- ASSERT_EQ(1U, functions.size());
-
- Module::Function *function = functions[0];
- EXPECT_EQ(0xf2cfda36ecf7f46dLL, function->address);
- EXPECT_LT(0U, function->size); // should have used dummy size
- EXPECT_EQ(0U, function->parameter_size);
- ASSERT_EQ(0U, function->lines.size());
-}
-
-TEST(InferSizes, LineSize) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // Feed in a simple compilation unit that defines a function with
- // one line.
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xb4513962eff94e92LL,
- "build-directory"));
- EXPECT_TRUE(h.StartFunction("function", 0xb4513962eff94e92LL));
- EXPECT_TRUE(h.Line(0xb4513962eff94e92LL, "source-file-name-1", 77396614));
- EXPECT_TRUE(h.Line(0xb4513963eff94e92LL, "source-file-name-2", 87660088));
- EXPECT_TRUE(h.EndFunction(0)); // unknown function end address
- EXPECT_TRUE(h.EndCompilationUnit(0)); // unknown CU end address
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit-2", 0xb4523963eff94e92LL,
- "build-directory-2")); // next boundary
- EXPECT_TRUE(h.EndCompilationUnit(0));
- h.Finalize();
-
- // Now check to see what has been added to the Module.
- Module::File *file1 = m.FindExistingFile("source-file-name-1");
- ASSERT_TRUE(file1 != NULL);
- Module::File *file2 = m.FindExistingFile("source-file-name-2");
- ASSERT_TRUE(file2 != NULL);
-
- vector<Module::Function *> functions;
- m.GetFunctions(&functions, functions.end());
- ASSERT_EQ((size_t) 1, functions.size());
-
- Module::Function *function = functions[0];
- EXPECT_STREQ("function", function->name.c_str());
- EXPECT_EQ(0xb4513962eff94e92LL, function->address);
- EXPECT_EQ(0x1000100000000ULL, function->size); // inferred from CU end
- EXPECT_EQ(0U, function->parameter_size);
- ASSERT_EQ((size_t) 2, function->lines.size());
-
- Module::Line *line1 = &function->lines[0];
- EXPECT_EQ(0xb4513962eff94e92LL, line1->address);
- EXPECT_EQ(0x100000000ULL, line1->size); // derived from EndFunction
- EXPECT_TRUE(line1->file == file1);
- EXPECT_EQ(77396614, line1->number);
-
- Module::Line *line2 = &function->lines[1];
- EXPECT_EQ(0xb4513963eff94e92LL, line2->address);
- EXPECT_EQ(0x1000000000000ULL, line2->size); // derived from EndFunction
- EXPECT_TRUE(line2->file == file2);
- EXPECT_EQ(87660088, line2->number);
-}
-
-#ifdef __GNUC__
-// Function name mangling can vary by compiler, so only run mangled-name
-// tests on GCC for simplicity's sake.
-TEST(FunctionNames, Mangled) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // Compilation unit with one function, mangled name.
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0xf2cfda63cef7f46cLL,
- "build-directory"));
- EXPECT_TRUE(h.StartFunction("_ZNSt6vectorIySaIyEE9push_backERKy",
- 0xf2cfda63cef7f46dLL));
- EXPECT_TRUE(h.EndFunction(0));
- EXPECT_TRUE(h.EndCompilationUnit(0));
-
- h.Finalize();
-
- // Now check to see what has been added to the Module.
- Module::File *file = m.FindExistingFile("compilation-unit");
- ASSERT_TRUE(file != NULL);
-
- vector<Module::Function *> functions;
- m.GetFunctions(&functions, functions.end());
- ASSERT_EQ(1U, functions.size());
-
- Module::Function *function = functions[0];
- // This is GCC-specific, but we shouldn't be seeing STABS data anywhere
- // but Linux.
- EXPECT_STREQ("std::vector<unsigned long long, "
- "std::allocator<unsigned long long> >::"
- "push_back(unsigned long long const&)",
- function->name.c_str());
- EXPECT_EQ(0xf2cfda63cef7f46dLL, function->address);
- EXPECT_LT(0U, function->size); // should have used dummy size
- EXPECT_EQ(0U, function->parameter_size);
- ASSERT_EQ(0U, function->lines.size());
-}
-#endif // __GNUC__
-
-// The GNU toolchain can omit functions that are not used; however,
-// when it does so, it doesn't clean up the debugging information that
-// refers to them. In STABS, this results in compilation units whose
-// SO addresses are zero.
-TEST(Omitted, Function) {
- Module m("name", "os", "arch", "id");
- StabsToModule h(&m);
-
- // The StartCompilationUnit and EndCompilationUnit calls may both have an
- // address of zero if the compilation unit has had sections removed.
- EXPECT_TRUE(h.StartCompilationUnit("compilation-unit", 0, "build-directory"));
- EXPECT_TRUE(h.StartFunction("function", 0x2a133596));
- EXPECT_TRUE(h.EndFunction(0));
- EXPECT_TRUE(h.EndCompilationUnit(0));
-}
-
-// TODO --- if we actually cared about STABS. Even without these we've
-// got full coverage of non-failure source lines in dump_stabs.cc.
-
-// Line size from next line
-// Line size from function end
-// Line size from next function start
-// line size from cu end
-// line size from next cu start
-// fallback size is something plausible
-
-// function size from function end
-// function size from next function start
-// function size from cu end
-// function size from next cu start
-// fallback size is something plausible
-
-// omitting functions outside the compilation unit's address range
-// zero-line, one-line, many-line functions
diff --git a/toolkit/crashreporter/google-breakpad/src/common/stdio_wrapper.h b/toolkit/crashreporter/google-breakpad/src/common/stdio_wrapper.h
deleted file mode 100644
index a3dd50aab..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/stdio_wrapper.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2016, 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_COMMON_STDIO_WRAPPER_H
-#define GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
-
-#include <stdio.h>
-
-#if defined(_MSC_VER) && MSC_VER < 1900
-#include <basetsd.h>
-
-#define snprintf _snprintf
-typedef SSIZE_T ssize_t;
-#endif
-
-
-#endif // GOOGLE_BREAKPAD_COMMON_STDIO_WRAPPER_H
diff --git a/toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc b/toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc
deleted file mode 100644
index 9c0d623fc..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/string_conversion.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <string.h>
-
-#include "common/convert_UTF.h"
-#include "common/scoped_ptr.h"
-#include "common/string_conversion.h"
-#include "common/using_std_string.h"
-
-namespace google_breakpad {
-
-using std::vector;
-
-void UTF8ToUTF16(const char *in, vector<uint16_t> *out) {
- size_t source_length = strlen(in);
- const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
- const UTF8 *source_end_ptr = source_ptr + source_length;
- // Erase the contents and zero fill to the expected size
- out->clear();
- out->insert(out->begin(), source_length, 0);
- uint16_t *target_ptr = &(*out)[0];
- uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t);
- ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
- &target_ptr, target_end_ptr,
- strictConversion);
-
- // Resize to be the size of the # of converted characters + NULL
- out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
-}
-
-int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]) {
- const UTF8 *source_ptr = reinterpret_cast<const UTF8 *>(in);
- const UTF8 *source_end_ptr = source_ptr + sizeof(char);
- uint16_t *target_ptr = out;
- uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t);
- out[0] = out[1] = 0;
-
- // Process one character at a time
- while (1) {
- ConversionResult result = ConvertUTF8toUTF16(&source_ptr, source_end_ptr,
- &target_ptr, target_end_ptr,
- strictConversion);
-
- if (result == conversionOK)
- return static_cast<int>(source_ptr - reinterpret_cast<const UTF8 *>(in));
-
- // Add another character to the input stream and try again
- source_ptr = reinterpret_cast<const UTF8 *>(in);
- ++source_end_ptr;
-
- if (source_end_ptr > reinterpret_cast<const UTF8 *>(in) + in_length)
- break;
- }
-
- return 0;
-}
-
-void UTF32ToUTF16(const wchar_t *in, vector<uint16_t> *out) {
- size_t source_length = wcslen(in);
- const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(in);
- const UTF32 *source_end_ptr = source_ptr + source_length;
- // Erase the contents and zero fill to the expected size
- out->clear();
- out->insert(out->begin(), source_length, 0);
- uint16_t *target_ptr = &(*out)[0];
- uint16_t *target_end_ptr = target_ptr + out->capacity() * sizeof(uint16_t);
- ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
- &target_ptr, target_end_ptr,
- strictConversion);
-
- // Resize to be the size of the # of converted characters + NULL
- out->resize(result == conversionOK ? target_ptr - &(*out)[0] + 1: 0);
-}
-
-void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]) {
- const UTF32 *source_ptr = reinterpret_cast<const UTF32 *>(&in);
- const UTF32 *source_end_ptr = source_ptr + 1;
- uint16_t *target_ptr = out;
- uint16_t *target_end_ptr = target_ptr + 2 * sizeof(uint16_t);
- out[0] = out[1] = 0;
- ConversionResult result = ConvertUTF32toUTF16(&source_ptr, source_end_ptr,
- &target_ptr, target_end_ptr,
- strictConversion);
-
- if (result != conversionOK) {
- out[0] = out[1] = 0;
- }
-}
-
-static inline uint16_t Swap(uint16_t value) {
- return (value >> 8) | static_cast<uint16_t>(value << 8);
-}
-
-string UTF16ToUTF8(const vector<uint16_t> &in, bool swap) {
- const UTF16 *source_ptr = &in[0];
- scoped_array<uint16_t> source_buffer;
-
- // If we're to swap, we need to make a local copy and swap each byte pair
- if (swap) {
- int idx = 0;
- source_buffer.reset(new uint16_t[in.size()]);
- UTF16 *source_buffer_ptr = source_buffer.get();
- for (vector<uint16_t>::const_iterator it = in.begin();
- it != in.end(); ++it, ++idx)
- source_buffer_ptr[idx] = Swap(*it);
-
- source_ptr = source_buffer.get();
- }
-
- // The maximum expansion would be 4x the size of the input string.
- const UTF16 *source_end_ptr = source_ptr + in.size();
- size_t target_capacity = in.size() * 4;
- scoped_array<UTF8> target_buffer(new UTF8[target_capacity]);
- UTF8 *target_ptr = target_buffer.get();
- UTF8 *target_end_ptr = target_ptr + target_capacity;
- ConversionResult result = ConvertUTF16toUTF8(&source_ptr, source_end_ptr,
- &target_ptr, target_end_ptr,
- strictConversion);
-
- if (result == conversionOK) {
- const char *targetPtr = reinterpret_cast<const char *>(target_buffer.get());
- return targetPtr;
- }
-
- return "";
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/string_conversion.h b/toolkit/crashreporter/google-breakpad/src/common/string_conversion.h
deleted file mode 100644
index b9ba96a2e..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/string_conversion.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// string_conversion.h: Conversion between different UTF-8/16/32 encodings.
-
-#ifndef COMMON_STRING_CONVERSION_H__
-#define COMMON_STRING_CONVERSION_H__
-
-#include <string>
-#include <vector>
-
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-
-using std::vector;
-
-// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the
-// conversion failed, |out| will be zero length.
-void UTF8ToUTF16(const char *in, vector<uint16_t> *out);
-
-// Convert at least one character (up to a maximum of |in_length|) from |in|
-// to UTF-16 into |out|. Return the number of characters consumed from |in|.
-// Any unused characters in |out| will be initialized to 0. No memory will
-// be allocated by this routine.
-int UTF8ToUTF16Char(const char *in, int in_length, uint16_t out[2]);
-
-// Convert |in| to UTF-16 into |out|. Use platform byte ordering. If the
-// conversion failed, |out| will be zero length.
-void UTF32ToUTF16(const wchar_t *in, vector<uint16_t> *out);
-
-// Convert |in| to UTF-16 into |out|. Any unused characters in |out| will be
-// initialized to 0. No memory will be allocated by this routine.
-void UTF32ToUTF16Char(wchar_t in, uint16_t out[2]);
-
-// Convert |in| to UTF-8. If |swap| is true, swap bytes before converting.
-string UTF16ToUTF8(const vector<uint16_t> &in, bool swap);
-
-} // namespace google_breakpad
-
-#endif // COMMON_STRING_CONVERSION_H__
diff --git a/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h b/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h
deleted file mode 100644
index 2cf15a855..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/symbol_data.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// -*- mode: c++ -*-
-
-// Copyright (c) 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 COMMON_SYMBOL_DATA_H_
-#define COMMON_SYMBOL_DATA_H_
-
-// Control what data is used from the symbol file.
-enum SymbolData {
- ALL_SYMBOL_DATA,
- NO_CFI,
- ONLY_CFI
-};
-
-#endif // COMMON_SYMBOL_DATA_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc b/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
deleted file mode 100644
index 1e783b45c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.cc
+++ /dev/null
@@ -1,359 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// test_assembler.cc: Implementation of google_breakpad::TestAssembler.
-// See test_assembler.h for details.
-
-#include "common/test_assembler.h"
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <iterator>
-
-namespace google_breakpad {
-namespace test_assembler {
-
-using std::back_insert_iterator;
-
-Label::Label() : value_(new Binding()) { }
-Label::Label(uint64_t value) : value_(new Binding(value)) { }
-Label::Label(const Label &label) {
- value_ = label.value_;
- value_->Acquire();
-}
-Label::~Label() {
- if (value_->Release()) delete value_;
-}
-
-Label &Label::operator=(uint64_t value) {
- value_->Set(NULL, value);
- return *this;
-}
-
-Label &Label::operator=(const Label &label) {
- value_->Set(label.value_, 0);
- return *this;
-}
-
-Label Label::operator+(uint64_t addend) const {
- Label l;
- l.value_->Set(this->value_, addend);
- return l;
-}
-
-Label Label::operator-(uint64_t subtrahend) const {
- Label l;
- l.value_->Set(this->value_, -subtrahend);
- return l;
-}
-
-// When NDEBUG is #defined, assert doesn't evaluate its argument. This
-// means you can't simply use assert to check the return value of a
-// function with necessary side effects.
-//
-// ALWAYS_EVALUATE_AND_ASSERT(x) evaluates x regardless of whether
-// NDEBUG is #defined; when NDEBUG is not #defined, it further asserts
-// that x is true.
-#ifdef NDEBUG
-#define ALWAYS_EVALUATE_AND_ASSERT(x) x
-#else
-#define ALWAYS_EVALUATE_AND_ASSERT(x) assert(x)
-#endif
-
-uint64_t Label::operator-(const Label &label) const {
- uint64_t offset;
- ALWAYS_EVALUATE_AND_ASSERT(IsKnownOffsetFrom(label, &offset));
- return offset;
-}
-
-uint64_t Label::Value() const {
- uint64_t v = 0;
- ALWAYS_EVALUATE_AND_ASSERT(IsKnownConstant(&v));
- return v;
-};
-
-bool Label::IsKnownConstant(uint64_t *value_p) const {
- Binding *base;
- uint64_t addend;
- value_->Get(&base, &addend);
- if (base != NULL) return false;
- if (value_p) *value_p = addend;
- return true;
-}
-
-bool Label::IsKnownOffsetFrom(const Label &label, uint64_t *offset_p) const
-{
- Binding *label_base, *this_base;
- uint64_t label_addend, this_addend;
- label.value_->Get(&label_base, &label_addend);
- value_->Get(&this_base, &this_addend);
- // If this and label are related, Get will find their final
- // common ancestor, regardless of how indirect the relation is. This
- // comparison also handles the constant vs. constant case.
- if (this_base != label_base) return false;
- if (offset_p) *offset_p = this_addend - label_addend;
- return true;
-}
-
-Label::Binding::Binding() : base_(this), addend_(), reference_count_(1) { }
-
-Label::Binding::Binding(uint64_t addend)
- : base_(NULL), addend_(addend), reference_count_(1) { }
-
-Label::Binding::~Binding() {
- assert(reference_count_ == 0);
- if (base_ && base_ != this && base_->Release())
- delete base_;
-}
-
-void Label::Binding::Set(Binding *binding, uint64_t addend) {
- if (!base_ && !binding) {
- // We're equating two constants. This could be okay.
- assert(addend_ == addend);
- } else if (!base_) {
- // We are a known constant, but BINDING may not be, so turn the
- // tables and try to set BINDING's value instead.
- binding->Set(NULL, addend_ - addend);
- } else {
- if (binding) {
- // Find binding's final value. Since the final value is always either
- // completely unconstrained or a constant, never a reference to
- // another variable (otherwise, it wouldn't be final), this
- // guarantees we won't create cycles here, even for code like this:
- // l = m, m = n, n = l;
- uint64_t binding_addend;
- binding->Get(&binding, &binding_addend);
- addend += binding_addend;
- }
-
- // It seems likely that setting a binding to itself is a bug
- // (although I can imagine this might turn out to be helpful to
- // permit).
- assert(binding != this);
-
- if (base_ != this) {
- // Set the other bindings on our chain as well. Note that this
- // is sufficient even though binding relationships form trees:
- // All binding operations traverse their chains to the end, and
- // all bindings related to us share some tail of our chain, so
- // they will see the changes we make here.
- base_->Set(binding, addend - addend_);
- // We're not going to use base_ any more.
- if (base_->Release()) delete base_;
- }
-
- // Adopt BINDING as our base. Note that it should be correct to
- // acquire here, after the release above, even though the usual
- // reference-counting rules call for acquiring first, and then
- // releasing: the self-reference assertion above should have
- // complained if BINDING were 'this' or anywhere along our chain,
- // so we didn't release BINDING.
- if (binding) binding->Acquire();
- base_ = binding;
- addend_ = addend;
- }
-}
-
-void Label::Binding::Get(Binding **base, uint64_t *addend) {
- if (base_ && base_ != this) {
- // Recurse to find the end of our reference chain (the root of our
- // tree), and then rewrite every binding along the chain to refer
- // to it directly, adjusting addends appropriately. (This is why
- // this member function isn't this-const.)
- Binding *final_base;
- uint64_t final_addend;
- base_->Get(&final_base, &final_addend);
- if (final_base) final_base->Acquire();
- if (base_->Release()) delete base_;
- base_ = final_base;
- addend_ += final_addend;
- }
- *base = base_;
- *addend = addend_;
-}
-
-template<typename Inserter>
-static inline void InsertEndian(test_assembler::Endianness endianness,
- size_t size, uint64_t number, Inserter dest) {
- assert(size > 0);
- if (endianness == kLittleEndian) {
- for (size_t i = 0; i < size; i++) {
- *dest++ = (char) (number & 0xff);
- number >>= 8;
- }
- } else {
- assert(endianness == kBigEndian);
- // The loop condition is odd, but it's correct for size_t.
- for (size_t i = size - 1; i < size; i--)
- *dest++ = (char) ((number >> (i * 8)) & 0xff);
- }
-}
-
-Section &Section::Append(Endianness endianness, size_t size, uint64_t number) {
- InsertEndian(endianness, size, number,
- back_insert_iterator<string>(contents_));
- return *this;
-}
-
-Section &Section::Append(Endianness endianness, size_t size,
- const Label &label) {
- // If this label's value is known, there's no reason to waste an
- // entry in references_ on it.
- uint64_t value;
- if (label.IsKnownConstant(&value))
- return Append(endianness, size, value);
-
- // This will get caught when the references are resolved, but it's
- // nicer to find out earlier.
- assert(endianness != kUnsetEndian);
-
- references_.push_back(Reference(contents_.size(), endianness, size, label));
- contents_.append(size, 0);
- return *this;
-}
-
-#define ENDIANNESS_L kLittleEndian
-#define ENDIANNESS_B kBigEndian
-#define ENDIANNESS(e) ENDIANNESS_ ## e
-
-#define DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
- Section &Section::e ## bits(uint ## bits ## _t v) { \
- InsertEndian(ENDIANNESS(e), bits / 8, v, \
- back_insert_iterator<string>(contents_)); \
- return *this; \
- }
-
-#define DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits) \
- Section &Section::e ## bits(const Label &v) { \
- return Append(ENDIANNESS(e), bits / 8, v); \
- }
-
-// Define L16, B32, and friends.
-#define DEFINE_SHORT_APPEND_ENDIAN(e, bits) \
- DEFINE_SHORT_APPEND_NUMBER_ENDIAN(e, bits) \
- DEFINE_SHORT_APPEND_LABEL_ENDIAN(e, bits)
-
-DEFINE_SHORT_APPEND_LABEL_ENDIAN(L, 8);
-DEFINE_SHORT_APPEND_LABEL_ENDIAN(B, 8);
-DEFINE_SHORT_APPEND_ENDIAN(L, 16);
-DEFINE_SHORT_APPEND_ENDIAN(L, 32);
-DEFINE_SHORT_APPEND_ENDIAN(L, 64);
-DEFINE_SHORT_APPEND_ENDIAN(B, 16);
-DEFINE_SHORT_APPEND_ENDIAN(B, 32);
-DEFINE_SHORT_APPEND_ENDIAN(B, 64);
-
-#define DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
- Section &Section::D ## bits(uint ## bits ## _t v) { \
- InsertEndian(endianness_, bits / 8, v, \
- back_insert_iterator<string>(contents_)); \
- return *this; \
- }
-#define DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits) \
- Section &Section::D ## bits(const Label &v) { \
- return Append(endianness_, bits / 8, v); \
- }
-#define DEFINE_SHORT_APPEND_DEFAULT(bits) \
- DEFINE_SHORT_APPEND_NUMBER_DEFAULT(bits) \
- DEFINE_SHORT_APPEND_LABEL_DEFAULT(bits)
-
-DEFINE_SHORT_APPEND_LABEL_DEFAULT(8)
-DEFINE_SHORT_APPEND_DEFAULT(16);
-DEFINE_SHORT_APPEND_DEFAULT(32);
-DEFINE_SHORT_APPEND_DEFAULT(64);
-
-Section &Section::Append(const Section &section) {
- size_t base = contents_.size();
- contents_.append(section.contents_);
- for (vector<Reference>::const_iterator it = section.references_.begin();
- it != section.references_.end(); it++)
- references_.push_back(Reference(base + it->offset, it->endianness,
- it->size, it->label));
- return *this;
-}
-
-Section &Section::LEB128(long long value) {
- while (value < -0x40 || 0x3f < value) {
- contents_ += (value & 0x7f) | 0x80;
- if (value < 0)
- value = (value >> 7) | ~(((unsigned long long) -1) >> 7);
- else
- value = (value >> 7);
- }
- contents_ += value & 0x7f;
- return *this;
-}
-
-Section &Section::ULEB128(uint64_t value) {
- while (value > 0x7f) {
- contents_ += (value & 0x7f) | 0x80;
- value = (value >> 7);
- }
- contents_ += value;
- return *this;
-}
-
-Section &Section::Align(size_t alignment, uint8_t pad_byte) {
- // ALIGNMENT must be a power of two.
- assert(((alignment - 1) & alignment) == 0);
- size_t new_size = (contents_.size() + alignment - 1) & ~(alignment - 1);
- contents_.append(new_size - contents_.size(), pad_byte);
- assert((contents_.size() & (alignment - 1)) == 0);
- return *this;
-}
-
-void Section::Clear() {
- contents_.clear();
- references_.clear();
-}
-
-bool Section::GetContents(string *contents) {
- // For each label reference, find the label's value, and patch it into
- // the section's contents.
- for (size_t i = 0; i < references_.size(); i++) {
- Reference &r = references_[i];
- uint64_t value;
- if (!r.label.IsKnownConstant(&value)) {
- fprintf(stderr, "Undefined label #%zu at offset 0x%zx\n", i, r.offset);
- return false;
- }
- assert(r.offset < contents_.size());
- assert(contents_.size() - r.offset >= r.size);
- InsertEndian(r.endianness, r.size, value, contents_.begin() + r.offset);
- }
- contents->clear();
- std::swap(contents_, *contents);
- references_.clear();
- return true;
-}
-
-} // namespace test_assembler
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.h b/toolkit/crashreporter/google-breakpad/src/common/test_assembler.h
deleted file mode 100644
index 373dbebac..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/test_assembler.h
+++ /dev/null
@@ -1,484 +0,0 @@
-// -*- mode: C++ -*-
-
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// test-assembler.h: interface to class for building complex binary streams.
-
-// To test the Breakpad symbol dumper and processor thoroughly, for
-// all combinations of host system and minidump processor
-// architecture, we need to be able to easily generate complex test
-// data like debugging information and minidump files.
-//
-// For example, if we want our unit tests to provide full code
-// coverage for stack walking, it may be difficult to persuade the
-// compiler to generate every possible sort of stack walking
-// information that we want to support; there are probably DWARF CFI
-// opcodes that GCC never emits. Similarly, if we want to test our
-// error handling, we will need to generate damaged minidumps or
-// debugging information that (we hope) the client or compiler will
-// never produce on its own.
-//
-// google_breakpad::TestAssembler provides a predictable and
-// (relatively) simple way to generate complex formatted data streams
-// like minidumps and CFI. Furthermore, because TestAssembler is
-// portable, developers without access to (say) Visual Studio or a
-// SPARC assembler can still work on test data for those targets.
-
-#ifndef PROCESSOR_TEST_ASSEMBLER_H_
-#define PROCESSOR_TEST_ASSEMBLER_H_
-
-#include <list>
-#include <vector>
-#include <string>
-
-#include "common/using_std_string.h"
-#include "google_breakpad/common/breakpad_types.h"
-
-namespace google_breakpad {
-
-using std::list;
-using std::vector;
-
-namespace test_assembler {
-
-// A Label represents a value not yet known that we need to store in a
-// section. As long as all the labels a section refers to are defined
-// by the time we retrieve its contents as bytes, we can use undefined
-// labels freely in that section's construction.
-//
-// A label can be in one of three states:
-// - undefined,
-// - defined as the sum of some other label and a constant, or
-// - a constant.
-//
-// A label's value never changes, but it can accumulate constraints.
-// Adding labels and integers is permitted, and yields a label.
-// Subtracting a constant from a label is permitted, and also yields a
-// label. Subtracting two labels that have some relationship to each
-// other is permitted, and yields a constant.
-//
-// For example:
-//
-// Label a; // a's value is undefined
-// Label b; // b's value is undefined
-// {
-// Label c = a + 4; // okay, even though a's value is unknown
-// b = c + 4; // also okay; b is now a+8
-// }
-// Label d = b - 2; // okay; d == a+6, even though c is gone
-// d.Value(); // error: d's value is not yet known
-// d - a; // is 6, even though their values are not known
-// a = 12; // now b == 20, and d == 18
-// d.Value(); // 18: no longer an error
-// b.Value(); // 20
-// d = 10; // error: d is already defined.
-//
-// Label objects' lifetimes are unconstrained: notice that, in the
-// above example, even though a and b are only related through c, and
-// c goes out of scope, the assignment to a sets b's value as well. In
-// particular, it's not necessary to ensure that a Label lives beyond
-// Sections that refer to it.
-class Label {
- public:
- Label(); // An undefined label.
- Label(uint64_t value); // A label with a fixed value
- Label(const Label &value); // A label equal to another.
- ~Label();
-
- // Return this label's value; it must be known.
- //
- // Providing this as a cast operator is nifty, but the conversions
- // happen in unexpected places. In particular, ISO C++ says that
- // Label + size_t becomes ambigious, because it can't decide whether
- // to convert the Label to a uint64_t and then to a size_t, or use
- // the overloaded operator that returns a new label, even though the
- // former could fail if the label is not yet defined and the latter won't.
- uint64_t Value() const;
-
- Label &operator=(uint64_t value);
- Label &operator=(const Label &value);
- Label operator+(uint64_t addend) const;
- Label operator-(uint64_t subtrahend) const;
- uint64_t operator-(const Label &subtrahend) const;
-
- // We could also provide == and != that work on undefined, but
- // related, labels.
-
- // Return true if this label's value is known. If VALUE_P is given,
- // set *VALUE_P to the known value if returning true.
- bool IsKnownConstant(uint64_t *value_p = NULL) const;
-
- // Return true if the offset from LABEL to this label is known. If
- // OFFSET_P is given, set *OFFSET_P to the offset when returning true.
- //
- // You can think of l.KnownOffsetFrom(m, &d) as being like 'd = l-m',
- // except that it also returns a value indicating whether the
- // subtraction is possible given what we currently know of l and m.
- // It can be possible even if we don't know l and m's values. For
- // example:
- //
- // Label l, m;
- // m = l + 10;
- // l.IsKnownConstant(); // false
- // m.IsKnownConstant(); // false
- // uint64_t d;
- // l.IsKnownOffsetFrom(m, &d); // true, and sets d to -10.
- // l-m // -10
- // m-l // 10
- // m.Value() // error: m's value is not known
- bool IsKnownOffsetFrom(const Label &label, uint64_t *offset_p = NULL) const;
-
- private:
- // A label's value, or if that is not yet known, how the value is
- // related to other labels' values. A binding may be:
- // - a known constant,
- // - constrained to be equal to some other binding plus a constant, or
- // - unconstrained, and free to take on any value.
- //
- // Many labels may point to a single binding, and each binding may
- // refer to another, so bindings and labels form trees whose leaves
- // are labels, whose interior nodes (and roots) are bindings, and
- // where links point from children to parents. Bindings are
- // reference counted, allowing labels to be lightweight, copyable,
- // assignable, placed in containers, and so on.
- class Binding {
- public:
- Binding();
- Binding(uint64_t addend);
- ~Binding();
-
- // Increment our reference count.
- void Acquire() { reference_count_++; };
- // Decrement our reference count, and return true if it is zero.
- bool Release() { return --reference_count_ == 0; }
-
- // Set this binding to be equal to BINDING + ADDEND. If BINDING is
- // NULL, then set this binding to the known constant ADDEND.
- // Update every binding on this binding's chain to point directly
- // to BINDING, or to be a constant, with addends adjusted
- // appropriately.
- void Set(Binding *binding, uint64_t value);
-
- // Return what we know about the value of this binding.
- // - If this binding's value is a known constant, set BASE to
- // NULL, and set ADDEND to its value.
- // - If this binding is not a known constant but related to other
- // bindings, set BASE to the binding at the end of the relation
- // chain (which will always be unconstrained), and set ADDEND to the
- // value to add to that binding's value to get this binding's
- // value.
- // - If this binding is unconstrained, set BASE to this, and leave
- // ADDEND unchanged.
- void Get(Binding **base, uint64_t *addend);
-
- private:
- // There are three cases:
- //
- // - A binding representing a known constant value has base_ NULL,
- // and addend_ equal to the value.
- //
- // - A binding representing a completely unconstrained value has
- // base_ pointing to this; addend_ is unused.
- //
- // - A binding whose value is related to some other binding's
- // value has base_ pointing to that other binding, and addend_
- // set to the amount to add to that binding's value to get this
- // binding's value. We only represent relationships of the form
- // x = y+c.
- //
- // Thus, the bind_ links form a chain terminating in either a
- // known constant value or a completely unconstrained value. Most
- // operations on bindings do path compression: they change every
- // binding on the chain to point directly to the final value,
- // adjusting addends as appropriate.
- Binding *base_;
- uint64_t addend_;
-
- // The number of Labels and Bindings pointing to this binding.
- // (When a binding points to itself, indicating a completely
- // unconstrained binding, that doesn't count as a reference.)
- int reference_count_;
- };
-
- // This label's value.
- Binding *value_;
-};
-
-inline Label operator+(uint64_t a, const Label &l) { return l + a; }
-// Note that int-Label isn't defined, as negating a Label is not an
-// operation we support.
-
-// Conventions for representing larger numbers as sequences of bytes.
-enum Endianness {
- kBigEndian, // Big-endian: the most significant byte comes first.
- kLittleEndian, // Little-endian: the least significant byte comes first.
- kUnsetEndian, // used internally
-};
-
-// A section is a sequence of bytes, constructed by appending bytes
-// to the end. Sections have a convenient and flexible set of member
-// functions for appending data in various formats: big-endian and
-// little-endian signed and unsigned values of different sizes;
-// LEB128 and ULEB128 values (see below), and raw blocks of bytes.
-//
-// If you need to append a value to a section that is not convenient
-// to compute immediately, you can create a label, append the
-// label's value to the section, and then set the label's value
-// later, when it's convenient to do so. Once a label's value is
-// known, the section class takes care of updating all previously
-// appended references to it.
-//
-// Once all the labels to which a section refers have had their
-// values determined, you can get a copy of the section's contents
-// as a string.
-//
-// Note that there is no specified "start of section" label. This is
-// because there are typically several different meanings for "the
-// start of a section": the offset of the section within an object
-// file, the address in memory at which the section's content appear,
-// and so on. It's up to the code that uses the Section class to
-// keep track of these explicitly, as they depend on the application.
-class Section {
- public:
- Section(Endianness endianness = kUnsetEndian)
- : endianness_(endianness) { };
-
- // A base class destructor should be either public and virtual,
- // or protected and nonvirtual.
- virtual ~Section() { };
-
- // Set the default endianness of this section to ENDIANNESS. This
- // sets the behavior of the D<N> appending functions. If the
- // assembler's default endianness was set, this is the
- void set_endianness(Endianness endianness) {
- endianness_ = endianness;
- }
-
- // Return the default endianness of this section.
- Endianness endianness() const { return endianness_; }
-
- // Append the SIZE bytes at DATA or the contents of STRING to the
- // end of this section. Return a reference to this section.
- Section &Append(const uint8_t *data, size_t size) {
- contents_.append(reinterpret_cast<const char *>(data), size);
- return *this;
- };
- Section &Append(const string &data) {
- contents_.append(data);
- return *this;
- };
-
- // Append SIZE copies of BYTE to the end of this section. Return a
- // reference to this section.
- Section &Append(size_t size, uint8_t byte) {
- contents_.append(size, (char) byte);
- return *this;
- }
-
- // Append NUMBER to this section. ENDIANNESS is the endianness to
- // use to write the number. SIZE is the length of the number in
- // bytes. Return a reference to this section.
- Section &Append(Endianness endianness, size_t size, uint64_t number);
- Section &Append(Endianness endianness, size_t size, const Label &label);
-
- // Append SECTION to the end of this section. The labels SECTION
- // refers to need not be defined yet.
- //
- // Note that this has no effect on any Labels' values, or on
- // SECTION. If placing SECTION within 'this' provides new
- // constraints on existing labels' values, then it's up to the
- // caller to fiddle with those labels as needed.
- Section &Append(const Section &section);
-
- // Append the contents of DATA as a series of bytes terminated by
- // a NULL character.
- Section &AppendCString(const string &data) {
- Append(data);
- contents_ += '\0';
- return *this;
- }
-
- // Append at most SIZE bytes from DATA; if DATA is less than SIZE bytes
- // long, pad with '\0' characters.
- Section &AppendCString(const string &data, size_t size) {
- contents_.append(data, 0, size);
- if (data.size() < size)
- Append(size - data.size(), 0);
- return *this;
- }
-
- // Append VALUE or LABEL to this section, with the given bit width and
- // endianness. Return a reference to this section.
- //
- // The names of these functions have the form <ENDIANNESS><BITWIDTH>:
- // <ENDIANNESS> is either 'L' (little-endian, least significant byte first),
- // 'B' (big-endian, most significant byte first), or
- // 'D' (default, the section's default endianness)
- // <BITWIDTH> is 8, 16, 32, or 64.
- //
- // Since endianness doesn't matter for a single byte, all the
- // <BITWIDTH>=8 functions are equivalent.
- //
- // These can be used to write both signed and unsigned values, as
- // the compiler will properly sign-extend a signed value before
- // passing it to the function, at which point the function's
- // behavior is the same either way.
- Section &L8(uint8_t value) { contents_ += value; return *this; }
- Section &B8(uint8_t value) { contents_ += value; return *this; }
- Section &D8(uint8_t value) { contents_ += value; return *this; }
- Section &L16(uint16_t), &L32(uint32_t), &L64(uint64_t),
- &B16(uint16_t), &B32(uint32_t), &B64(uint64_t),
- &D16(uint16_t), &D32(uint32_t), &D64(uint64_t);
- Section &L8(const Label &label), &L16(const Label &label),
- &L32(const Label &label), &L64(const Label &label),
- &B8(const Label &label), &B16(const Label &label),
- &B32(const Label &label), &B64(const Label &label),
- &D8(const Label &label), &D16(const Label &label),
- &D32(const Label &label), &D64(const Label &label);
-
- // Append VALUE in a signed LEB128 (Little-Endian Base 128) form.
- //
- // The signed LEB128 representation of an integer N is a variable
- // number of bytes:
- //
- // - If N is between -0x40 and 0x3f, then its signed LEB128
- // representation is a single byte whose value is N.
- //
- // - Otherwise, its signed LEB128 representation is (N & 0x7f) |
- // 0x80, followed by the signed LEB128 representation of N / 128,
- // rounded towards negative infinity.
- //
- // In other words, we break VALUE into groups of seven bits, put
- // them in little-endian order, and then write them as eight-bit
- // bytes with the high bit on all but the last.
- //
- // Note that VALUE cannot be a Label (we would have to implement
- // relaxation).
- Section &LEB128(long long value);
-
- // Append VALUE in unsigned LEB128 (Little-Endian Base 128) form.
- //
- // The unsigned LEB128 representation of an integer N is a variable
- // number of bytes:
- //
- // - If N is between 0 and 0x7f, then its unsigned LEB128
- // representation is a single byte whose value is N.
- //
- // - Otherwise, its unsigned LEB128 representation is (N & 0x7f) |
- // 0x80, followed by the unsigned LEB128 representation of N /
- // 128, rounded towards negative infinity.
- //
- // Note that VALUE cannot be a Label (we would have to implement
- // relaxation).
- Section &ULEB128(uint64_t value);
-
- // Jump to the next location aligned on an ALIGNMENT-byte boundary,
- // relative to the start of the section. Fill the gap with PAD_BYTE.
- // ALIGNMENT must be a power of two. Return a reference to this
- // section.
- Section &Align(size_t alignment, uint8_t pad_byte = 0);
-
- // Clear the contents of this section.
- void Clear();
-
- // Return the current size of the section.
- size_t Size() const { return contents_.size(); }
-
- // Return a label representing the start of the section.
- //
- // It is up to the user whether this label represents the section's
- // position in an object file, the section's address in memory, or
- // what have you; some applications may need both, in which case
- // this simple-minded interface won't be enough. This class only
- // provides a single start label, for use with the Here and Mark
- // member functions.
- //
- // Ideally, we'd provide this in a subclass that actually knows more
- // about the application at hand and can provide an appropriate
- // collection of start labels. But then the appending member
- // functions like Append and D32 would return a reference to the
- // base class, not the derived class, and the chaining won't work.
- // Since the only value here is in pretty notation, that's a fatal
- // flaw.
- Label start() const { return start_; }
-
- // Return a label representing the point at which the next Appended
- // item will appear in the section, relative to start().
- Label Here() const { return start_ + Size(); }
-
- // Set *LABEL to Here, and return a reference to this section.
- Section &Mark(Label *label) { *label = Here(); return *this; }
-
- // If there are no undefined label references left in this
- // section, set CONTENTS to the contents of this section, as a
- // string, and clear this section. Return true on success, or false
- // if there were still undefined labels.
- bool GetContents(string *contents);
-
- private:
- // Used internally. A reference to a label's value.
- struct Reference {
- Reference(size_t set_offset, Endianness set_endianness, size_t set_size,
- const Label &set_label)
- : offset(set_offset), endianness(set_endianness), size(set_size),
- label(set_label) { }
-
- // The offset of the reference within the section.
- size_t offset;
-
- // The endianness of the reference.
- Endianness endianness;
-
- // The size of the reference.
- size_t size;
-
- // The label to which this is a reference.
- Label label;
- };
-
- // The default endianness of this section.
- Endianness endianness_;
-
- // The contents of the section.
- string contents_;
-
- // References to labels within those contents.
- vector<Reference> references_;
-
- // A label referring to the beginning of the section.
- Label start_;
-};
-
-} // namespace test_assembler
-} // namespace google_breakpad
-
-#endif // PROCESSOR_TEST_ASSEMBLER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/test_assembler_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/test_assembler_unittest.cc
deleted file mode 100644
index 94b5a5ce5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/test_assembler_unittest.cc
+++ /dev/null
@@ -1,1662 +0,0 @@
-// 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.
-
-// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// test_assembler_unittest.cc: Unit tests for google_breakpad::TestAssembler.
-
-#include <string>
-#include <string.h>
-
-#include "breakpad_googletest_includes.h"
-#include "common/test_assembler.h"
-#include "common/using_std_string.h"
-
-using google_breakpad::test_assembler::Label;
-using google_breakpad::test_assembler::Section;
-using google_breakpad::test_assembler::kBigEndian;
-using google_breakpad::test_assembler::kLittleEndian;
-using testing::Test;
-
-TEST(ConstructLabel, Simple) {
- Label l;
-}
-
-TEST(ConstructLabel, Undefined) {
- Label l;
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(ConstructLabelDeathTest, Undefined) {
- Label l;
- ASSERT_DEATH(l.Value(), "IsKnownConstant\\(&v\\)");
-}
-
-TEST(ConstructLabel, Constant) {
- Label l(0x060b9f974eaf301eULL);
- uint64_t v;
- EXPECT_TRUE(l.IsKnownConstant(&v));
- EXPECT_EQ(v, 0x060b9f974eaf301eULL);
- EXPECT_EQ(l.Value(), 0x060b9f974eaf301eULL);
-}
-
-TEST(ConstructLabel, Copy) {
- Label l;
- Label m(l);
- uint64_t v;
- EXPECT_TRUE(l.IsKnownOffsetFrom(m, &v));
- EXPECT_EQ(0U, v);
-}
-
-// The left-hand-side of a label assignment can be either
-// unconstrained, related, or known. The right-hand-side can be any of
-// those, or an integer.
-TEST(Assignment, UnconstrainedToUnconstrained) {
- Label l, m;
- l = m;
- EXPECT_EQ(0U, l-m);
- EXPECT_TRUE(l.IsKnownOffsetFrom(m));
- uint64_t d;
- EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d));
- EXPECT_EQ(0U, d);
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(Assignment, UnconstrainedToRelated) {
- Label l, m, n;
- l = n;
- l = m;
- EXPECT_EQ(0U, l-m);
- EXPECT_TRUE(l.IsKnownOffsetFrom(m));
- uint64_t d;
- EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d));
- EXPECT_EQ(0U, d);
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(Assignment, UnconstrainedToKnown) {
- Label l, m;
- l = 0x8fd16e55b20a39c1ULL;
- l = m;
- EXPECT_EQ(0U, l-m);
- EXPECT_TRUE(l.IsKnownOffsetFrom(m));
- uint64_t d;
- EXPECT_TRUE(l.IsKnownOffsetFrom(m, &d));
- EXPECT_EQ(0U, d);
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x8fd16e55b20a39c1ULL, m.Value());
-}
-
-TEST(Assignment, RelatedToUnconstrained) {
- Label l, m, n;
- m = n;
- l = m;
- EXPECT_EQ(0U, l-n);
- EXPECT_TRUE(l.IsKnownOffsetFrom(n));
- uint64_t d;
- EXPECT_TRUE(l.IsKnownOffsetFrom(n, &d));
- EXPECT_EQ(0U, d);
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(Assignment, RelatedToRelated) {
- Label l, m, n, o;
- l = n;
- m = o;
- l = m;
- EXPECT_EQ(0U, n-o);
- EXPECT_TRUE(n.IsKnownOffsetFrom(o));
- uint64_t d;
- EXPECT_TRUE(n.IsKnownOffsetFrom(o, &d));
- EXPECT_EQ(0U, d);
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(Assignment, RelatedToKnown) {
- Label l, m, n;
- m = n;
- l = 0xd2011f8c82ad56f2ULL;
- l = m;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0xd2011f8c82ad56f2ULL, l.Value());
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0xd2011f8c82ad56f2ULL, m.Value());
- EXPECT_TRUE(n.IsKnownConstant());
- EXPECT_EQ(0xd2011f8c82ad56f2ULL, n.Value());
-}
-
-TEST(Assignment, KnownToUnconstrained) {
- Label l, m;
- m = 0x50b024c0d6073887ULL;
- l = m;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0x50b024c0d6073887ULL, l.Value());
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x50b024c0d6073887ULL, m.Value());
-}
-
-TEST(Assignment, KnownToRelated) {
- Label l, m, n;
- l = n;
- m = 0x5348883655c727e5ULL;
- l = m;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0x5348883655c727e5ULL, l.Value());
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x5348883655c727e5ULL, m.Value());
- EXPECT_TRUE(n.IsKnownConstant());
- EXPECT_EQ(0x5348883655c727e5ULL, n.Value());
-}
-
-TEST(Assignment, KnownToKnown) {
- Label l, m;
- l = 0x36c209c20987564eULL;
- m = 0x36c209c20987564eULL;
- l = m;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0x36c209c20987564eULL, l.Value());
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x36c209c20987564eULL, m.Value());
-}
-
-TEST(Assignment, ConstantToUnconstrained) {
- Label l;
- l = 0xc02495f4d7f5a957ULL;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0xc02495f4d7f5a957ULL, l.Value());
-}
-
-TEST(Assignment, ConstantToRelated) {
- Label l, m;
- l = m;
- l = 0x4577901cf275488dULL;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0x4577901cf275488dULL, l.Value());
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x4577901cf275488dULL, m.Value());
-}
-
-TEST(Assignment, ConstantToKnown) {
- Label l;
- l = 0xec0b9c369b7e8ea7ULL;
- l = 0xec0b9c369b7e8ea7ULL;
- EXPECT_TRUE(l.IsKnownConstant());
- EXPECT_EQ(0xec0b9c369b7e8ea7ULL, l.Value());
-}
-
-TEST(AssignmentDeathTest, Self) {
- Label l;
- ASSERT_DEATH(l = l, "binding != this");
-}
-
-TEST(AssignmentDeathTest, IndirectCycle) {
- Label l, m, n;
- l = m;
- m = n;
- ASSERT_DEATH(n = l, "binding != this");
-}
-
-TEST(AssignmentDeathTest, Cycle) {
- Label l, m, n, o;
- l = m;
- m = n;
- o = n;
- ASSERT_DEATH(o = l, "binding != this");
-}
-
-TEST(Addition, LabelConstant) {
- Label l, m;
- m = l + 0x5248d93e8bbe9497ULL;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(0x5248d93e8bbe9497ULL, d);
- EXPECT_FALSE(m.IsKnownConstant());
-}
-
-TEST(Addition, ConstantLabel) {
- Label l, m;
- m = 0xf51e94e00d6e3c84ULL + l;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(0xf51e94e00d6e3c84ULL, d);
- EXPECT_FALSE(m.IsKnownConstant());
-}
-
-TEST(Addition, KnownLabelConstant) {
- Label l, m;
- l = 0x16286307042ce0d8ULL;
- m = l + 0x3fdddd91306719d7ULL;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(0x3fdddd91306719d7ULL, d);
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x16286307042ce0d8ULL + 0x3fdddd91306719d7ULL, m.Value());
-}
-
-TEST(Addition, ConstantKnownLabel) {
- Label l, m;
- l = 0x50f62d0cdd1031deULL;
- m = 0x1b13462d8577c538ULL + l;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(0x1b13462d8577c538ULL, d);
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x50f62d0cdd1031deULL + 0x1b13462d8577c538ULL, m.Value());
-}
-
-TEST(Subtraction, LabelConstant) {
- Label l, m;
- m = l - 0x0620884d21d3138eULL;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(-0x0620884d21d3138eULL, d);
- EXPECT_FALSE(m.IsKnownConstant());
-}
-
-TEST(Subtraction, KnownLabelConstant) {
- Label l, m;
- l = 0x6237fbaf9ef7929eULL;
- m = l - 0x317730995d2ab6eeULL;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l));
- uint64_t d;
- EXPECT_TRUE(m.IsKnownOffsetFrom(l, &d));
- EXPECT_EQ(-0x317730995d2ab6eeULL, d);
- EXPECT_TRUE(m.IsKnownConstant());
- EXPECT_EQ(0x6237fbaf9ef7929eULL - 0x317730995d2ab6eeULL, m.Value());
-}
-
-TEST(SubtractionDeathTest, LabelLabel) {
- Label l, m;
- ASSERT_DEATH(l - m, "IsKnownOffsetFrom\\(label, &offset\\)");
-}
-
-TEST(Subtraction, LabelLabel) {
- Label l, m;
- l = m + 0x7fa77ec63e28a17aULL;
- EXPECT_EQ(0x7fa77ec63e28a17aULL, l - m);
- EXPECT_EQ(-0x7fa77ec63e28a17aULL, m - l);
-}
-
-TEST(IsKnownConstant, Undefined) {
- Label l;
- EXPECT_FALSE(l.IsKnownConstant());
-}
-
-TEST(IsKnownConstant, RelatedLabel) {
- Label l, m;
- l = m;
- EXPECT_FALSE(l.IsKnownConstant());
- EXPECT_FALSE(m.IsKnownConstant());
-}
-
-TEST(IsKnownConstant, Constant) {
- Label l;
- l = 0xf374b1bdd6a22576ULL;
- EXPECT_TRUE(l.IsKnownConstant());
-}
-
-TEST(IsKnownOffsetFrom, Unrelated) {
- Label l, m;
- EXPECT_FALSE(l.IsKnownOffsetFrom(m));
-}
-
-TEST(IsKnownOffsetFrom, Related) {
- Label l, m;
- l = m;
- EXPECT_TRUE(l.IsKnownOffsetFrom(m));
-}
-
-// Test the construction of chains of related labels, and the
-// propagation of values through them.
-//
-// Although the relations between labels are supposed to behave
-// symmetrically --- that is, 'a = b' should put a and b in
-// indistinguishable states --- there's a distinction made internally
-// between the target (a) and the source (b).
-//
-// So there are five test axes to cover:
-//
-// - Do we construct the chain with assignment ("Assign") or with constructors
-// ("Construct")?
-//
-// - Do we set the value of the label at the start of the chain
-// ("Start") or the label at the end ("End")?
-//
-// - Are we testing the propagation of a relationship between variable
-// values ("Relation"), or the propagation of a known constant value
-// ("Value")?
-//
-// - Do we set the value before building the chain ("Before") or after
-// the chain has been built ("After")?
-//
-// - Do we add new relationships to the end of the existing chain
-// ("Forward") or to the beginning ("Backward")?
-//
-// Of course, "Construct" and "Backward" can't be combined, which
-// eliminates eight combinations, and "Construct", "End", and "Before"
-// can't be combined, which eliminates two more, so there are are 22
-// combinations, not 32.
-
-TEST(LabelChain, AssignStartRelationBeforeForward) {
- Label a, b, c, d;
- Label x;
- a = x;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, AssignStartRelationBeforeBackward) {
- Label a, b, c, d;
- Label x;
- a = x;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, AssignStartRelationAfterForward) {
- Label a, b, c, d;
- Label x;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- a = x;
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, AssignStartRelationAfterBackward) {
- Label a, b, c, d;
- Label x;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- a = x;
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, AssignStartValueBeforeForward) {
- Label a, b, c, d;
- a = 0xa131200190546ac2ULL;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- EXPECT_EQ(0xa131200190546ac2ULL + 0x111U, d.Value());
- EXPECT_EQ(0xa131200190546ac2ULL + 0x11U, c.Value());
- EXPECT_EQ(0xa131200190546ac2ULL + 0x1U, b.Value());
- EXPECT_EQ(0xa131200190546ac2ULL + 0U, a.Value());
-}
-
-TEST(LabelChain, AssignStartValueBeforeBackward) {
- Label a, b, c, d;
- a = 0x8da17e1670ad4fa2ULL;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x111U, d.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x11U, c.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0x1U, b.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL + 0U, a.Value());
-}
-
-TEST(LabelChain, AssignStartValueAfterForward) {
- Label a, b, c, d;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- a = 0x99b8f51bafd41adaULL;
- EXPECT_EQ(0x99b8f51bafd41adaULL + 0x111U, d.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL + 0x11U, c.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL + 0x1U, b.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL + 0U, a.Value());
-}
-
-TEST(LabelChain, AssignStartValueAfterBackward) {
- Label a, b, c, d;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- a = 0xc86ca1d97ab5df6eULL;
- EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x111U, d.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x11U, c.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0x1U, b.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL + 0U, a.Value());
-}
-
-TEST(LabelChain, AssignEndRelationBeforeForward) {
- Label a, b, c, d;
- Label x;
- x = d;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- EXPECT_EQ(-(uint64_t)0x111U, a-x);
- EXPECT_EQ(-(uint64_t)0x110U, b-x);
- EXPECT_EQ(-(uint64_t)0x100U, c-x);
- EXPECT_EQ(-(uint64_t)0U, d-x);
-}
-
-TEST(LabelChain, AssignEndRelationBeforeBackward) {
- Label a, b, c, d;
- Label x;
- x = d;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- EXPECT_EQ(-(uint64_t)0x111U, a-x);
- EXPECT_EQ(-(uint64_t)0x110U, b-x);
- EXPECT_EQ(-(uint64_t)0x100U, c-x);
- EXPECT_EQ(-(uint64_t)0U, d-x);
-}
-
-TEST(LabelChain, AssignEndRelationAfterForward) {
- Label a, b, c, d;
- Label x;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- x = d;
- EXPECT_EQ(-(uint64_t)0x111U, a-x);
- EXPECT_EQ(-(uint64_t)0x110U, b-x);
- EXPECT_EQ(-(uint64_t)0x100U, c-x);
- EXPECT_EQ(-(uint64_t)0x000U, d-x);
-}
-
-TEST(LabelChain, AssignEndRelationAfterBackward) {
- Label a, b, c, d;
- Label x;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- x = d;
- EXPECT_EQ(-(uint64_t)0x111U, a-x);
- EXPECT_EQ(-(uint64_t)0x110U, b-x);
- EXPECT_EQ(-(uint64_t)0x100U, c-x);
- EXPECT_EQ(-(uint64_t)0x000U, d-x);
-}
-
-TEST(LabelChain, AssignEndValueBeforeForward) {
- Label a, b, c, d;
- d = 0xa131200190546ac2ULL;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- EXPECT_EQ(0xa131200190546ac2ULL - 0x111, a.Value());
- EXPECT_EQ(0xa131200190546ac2ULL - 0x110, b.Value());
- EXPECT_EQ(0xa131200190546ac2ULL - 0x100, c.Value());
- EXPECT_EQ(0xa131200190546ac2ULL - 0x000, d.Value());
-}
-
-TEST(LabelChain, AssignEndValueBeforeBackward) {
- Label a, b, c, d;
- d = 0x8da17e1670ad4fa2ULL;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x111, a.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x110, b.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x100, c.Value());
- EXPECT_EQ(0x8da17e1670ad4fa2ULL - 0x000, d.Value());
-}
-
-TEST(LabelChain, AssignEndValueAfterForward) {
- Label a, b, c, d;
- b = a + 0x1;
- c = b + 0x10;
- d = c + 0x100;
- d = 0x99b8f51bafd41adaULL;
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value());
-}
-
-TEST(LabelChain, AssignEndValueAfterBackward) {
- Label a, b, c, d;
- d = c + 0x100;
- c = b + 0x10;
- b = a + 0x1;
- d = 0xc86ca1d97ab5df6eULL;
- EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x111, a.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x110, b.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x100, c.Value());
- EXPECT_EQ(0xc86ca1d97ab5df6eULL - 0x000, d.Value());
-}
-
-TEST(LabelChain, ConstructStartRelationBeforeForward) {
- Label x;
- Label a(x);
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, ConstructStartRelationAfterForward) {
- Label x;
- Label a;
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- a = x;
- EXPECT_EQ(0x111U, d-x);
- EXPECT_EQ(0x11U, c-x);
- EXPECT_EQ(0x1U, b-x);
- EXPECT_EQ(0U, a-x);
-}
-
-TEST(LabelChain, ConstructStartValueBeforeForward) {
- Label a(0x5d234d177d01ccc8ULL);
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x111U, d.Value());
- EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x011U, c.Value());
- EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x001U, b.Value());
- EXPECT_EQ(0x5d234d177d01ccc8ULL + 0x000U, a.Value());
-}
-
-TEST(LabelChain, ConstructStartValueAfterForward) {
- Label a;
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- a = 0xded85d54586e84fcULL;
- EXPECT_EQ(0xded85d54586e84fcULL + 0x111U, d.Value());
- EXPECT_EQ(0xded85d54586e84fcULL + 0x011U, c.Value());
- EXPECT_EQ(0xded85d54586e84fcULL + 0x001U, b.Value());
- EXPECT_EQ(0xded85d54586e84fcULL + 0x000U, a.Value());
-}
-
-TEST(LabelChain, ConstructEndRelationAfterForward) {
- Label x;
- Label a;
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- x = d;
- EXPECT_EQ(-(uint64_t)0x111U, a-x);
- EXPECT_EQ(-(uint64_t)0x110U, b-x);
- EXPECT_EQ(-(uint64_t)0x100U, c-x);
- EXPECT_EQ(-(uint64_t)0x000U, d-x);
-}
-
-TEST(LabelChain, ConstructEndValueAfterForward) {
- Label a;
- Label b(a + 0x1);
- Label c(b + 0x10);
- Label d(c + 0x100);
- d = 0x99b8f51bafd41adaULL;
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x111, a.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x110, b.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x100, c.Value());
- EXPECT_EQ(0x99b8f51bafd41adaULL - 0x000, d.Value());
-}
-
-TEST(LabelTree, KnownValue) {
- Label l, m, n, o, p;
- l = m;
- m = n;
- o = p;
- p = n;
- l = 0x536b5de3d468a1b5ULL;
- EXPECT_EQ(0x536b5de3d468a1b5ULL, o.Value());
-}
-
-TEST(LabelTree, Related) {
- Label l, m, n, o, p;
- l = m - 1;
- m = n - 10;
- o = p + 100;
- p = n + 1000;
- EXPECT_EQ(1111U, o - l);
-}
-
-TEST(EquationDeathTest, EqualConstants) {
- Label m = 0x0d3962f280f07d24ULL;
- Label n = 0x0d3962f280f07d24ULL;
- m = n; // no death expected
-}
-
-TEST(EquationDeathTest, EqualIndirectConstants) {
- Label m = 0xa347f1e5238fe6a1ULL;
- Label n;
- Label o = n;
- n = 0xa347f1e5238fe6a1ULL;
- n = m; // no death expected
-}
-
-TEST(EquationDeathTest, ConstantClash) {
- Label m = 0xd4cc0f4f630ec741ULL;
- Label n = 0x934cd2d8254fc3eaULL;
- ASSERT_DEATH(m = n, "addend_ == addend");
-}
-
-TEST(EquationDeathTest, IndirectConstantClash) {
- Label m = 0xd4cc0f4f630ec741ULL;
- Label n, o;
- n = o;
- o = 0xcfbe3b83ac49ce86ULL;
- ASSERT_DEATH(m = n, "addend_ == addend");
-}
-
-// Assigning to a related label may free the next Binding on its
-// chain. This test always passes; it is interesting to memory
-// checkers and coverage analysis.
-TEST(LabelReferenceCount, AssignmentFree) {
- Label l;
- {
- Label m;
- l = m;
- }
- // This should free m's Binding.
- l = 0xca8bae92f0376d4fULL;
- ASSERT_EQ(0xca8bae92f0376d4fULL, l.Value());
-}
-
-// Finding the value of a label may free the Binding it refers to. This test
-// always passes; it is interesting to memory checkers and coverage analysis.
-TEST(LabelReferenceCount, FindValueFree) {
- Label l;
- {
- Label m, n;
- l = m;
- m = n;
- n = 0x7a0b0c576672daafULL;
- // At this point, l's Binding refers to m's Binding, which refers
- // to n's binding.
- }
- // Now, l is the only reference keeping the three Bindings alive.
- // Resolving its value should free l's and m's original bindings.
- ASSERT_EQ(0x7a0b0c576672daafULL, l.Value());
-}
-
-TEST(ConstructSection, Simple) {
- Section s;
-}
-
-TEST(ConstructSection, WithEndian) {
- Section s(kBigEndian);
-}
-
-// A fixture class for TestAssembler::Section tests.
-class SectionFixture {
- public:
- Section section;
- string contents;
- static const uint8_t data[];
- static const size_t data_size;
-};
-
-const uint8_t SectionFixture::data[] = {
- 0x87, 0x4f, 0x43, 0x67, 0x30, 0xd0, 0xd4, 0x0e
-};
-
-#define I0()
-#define I1(a) { a }
-#define I2(a,b) { a,b }
-#define I3(a,b,c) { a,b,c }
-#define I4(a,b,c,d) { a,b,c,d }
-#define I5(a,b,c,d,e) { a,b,c,d,e }
-#define I6(a,b,c,d,e,f) { a,b,c,d,e,f }
-#define I7(a,b,c,d,e,f,g) { a,b,c,d,e,f,g }
-#define I8(a,b,c,d,e,f,g,h) { a,b,c,d,e,f,g,h }
-#define I9(a,b,c,d,e,f,g,h,i) { a,b,c,d,e,f,g,h,i }
-#define ASSERT_BYTES(s, b) \
- do \
- { \
- static const uint8_t expected_bytes[] = b; \
- ASSERT_EQ(sizeof(expected_bytes), s.size()); \
- ASSERT_TRUE(memcmp(s.data(), (const char *) expected_bytes, \
- sizeof(expected_bytes)) == 0); \
- } \
- while(0)
-
-class Append: public SectionFixture, public Test { };
-
-TEST_F(Append, Bytes) {
- section.Append(data, sizeof(data));
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_EQ(sizeof(data), contents.size());
- EXPECT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data)));
-}
-
-TEST_F(Append, BytesTwice) {
- section.Append(data, sizeof(data));
- section.Append(data, sizeof(data));
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_EQ(2 * sizeof(data), contents.size());
- ASSERT_TRUE(0 == memcmp(contents.data(), (const char *) data, sizeof(data)));
- ASSERT_TRUE(0 == memcmp(contents.data() + sizeof(data),
- (const char *) data, sizeof(data)));
-}
-
-TEST_F(Append, String) {
- string s1 = "howdy ";
- string s2 = "there";
- section.Append(s1);
- section.Append(s2);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_STREQ(contents.c_str(), "howdy there");
-}
-
-TEST_F(Append, CString) {
- section.AppendCString("howdy");
- section.AppendCString("");
- section.AppendCString("there");
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_EQ(string("howdy\0\0there\0", 13), contents);
-}
-
-TEST_F(Append, CStringSize) {
- section.AppendCString("howdy", 3);
- section.AppendCString("there", 5);
- section.AppendCString("fred", 6);
- section.AppendCString("natalie", 0);
- section.AppendCString("", 10);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_EQ(string("howtherefred\0\0\0\0\0\0\0\0\0\0\0\0", 24), contents);
-}
-
-TEST_F(Append, RepeatedBytes) {
- section.Append((size_t) 10, '*');
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_STREQ(contents.c_str(), "**********");
-}
-
-TEST_F(Append, GeneralLE1) {
- section.Append(kLittleEndian, 1, 42);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I1(42));
-}
-
-TEST_F(Append, GeneralLE2) {
- section.Append(kLittleEndian, 2, 0x15a1);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0xa1, 0x15));
-}
-
-TEST_F(Append, GeneralLE3) {
- section.Append(kLittleEndian, 3, 0x59ae8d);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59));
-}
-
-TEST_F(Append, GeneralLE4) {
- section.Append(kLittleEndian, 4, 0x51603c56);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51));
-}
-
-TEST_F(Append, GeneralLE5) {
- section.Append(kLittleEndian, 5, 0x385e2803b4ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38));
-}
-
-TEST_F(Append, GeneralLE6) {
- section.Append(kLittleEndian, 6, 0xc7db9534dd1fULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7));
-}
-
-TEST_F(Append, GeneralLE7) {
- section.Append(kLittleEndian, 7, 0x1445c9f1b843e6ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14));
-}
-
-TEST_F(Append, GeneralLE8) {
- section.Append(kLittleEndian, 8, 0xaf48019dfe5c01e5ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf));
-}
-
-TEST_F(Append, GeneralBE1) {
- section.Append(kBigEndian, 1, 0xd0ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I1(0xd0));
-}
-
-TEST_F(Append, GeneralBE2) {
- section.Append(kBigEndian, 2, 0x2e7eULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2e, 0x7e));
-}
-
-TEST_F(Append, GeneralBE3) {
- section.Append(kBigEndian, 3, 0x37dad6ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6));
-}
-
-TEST_F(Append, GeneralBE4) {
- section.Append(kBigEndian, 4, 0x715935c7ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7));
-}
-
-TEST_F(Append, GeneralBE5) {
- section.Append(kBigEndian, 5, 0x42baeb02b7ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7));
-}
-
-TEST_F(Append, GeneralBE6) {
- section.Append(kBigEndian, 6, 0xf1cdf10e7b18ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18));
-}
-
-TEST_F(Append, GeneralBE7) {
- section.Append(kBigEndian, 7, 0xf50a724f0b0d20ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20));
-}
-
-TEST_F(Append, GeneralBE8) {
- section.Append(kBigEndian, 8, 0xa6b2cb5e98dc9c16ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16));
-}
-
-TEST_F(Append, GeneralLE1Label) {
- Label l;
- section.Append(kLittleEndian, 1, l);
- l = 42;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I1(42));
-}
-
-TEST_F(Append, GeneralLE2Label) {
- Label l;
- section.Append(kLittleEndian, 2, l);
- l = 0x15a1;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0xa1, 0x15));
-}
-
-TEST_F(Append, GeneralLE3Label) {
- Label l;
- section.Append(kLittleEndian, 3, l);
- l = 0x59ae8d;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x8d, 0xae, 0x59));
-}
-
-TEST_F(Append, GeneralLE4Label) {
- Label l;
- section.Append(kLittleEndian, 4, l);
- l = 0x51603c56;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I4(0x56, 0x3c, 0x60, 0x51));
-}
-
-TEST_F(Append, GeneralLE5Label) {
- Label l;
- section.Append(kLittleEndian, 5, l);
- l = 0x385e2803b4ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0xb4, 0x03, 0x28, 0x5e, 0x38));
-}
-
-TEST_F(Append, GeneralLE6Label) {
- Label l;
- section.Append(kLittleEndian, 6, l);
- l = 0xc7db9534dd1fULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I6(0x1f, 0xdd, 0x34, 0x95, 0xdb, 0xc7));
-}
-
-TEST_F(Append, GeneralLE7Label) {
- Label l;
- section.Append(kLittleEndian, 7, l);
- l = 0x1445c9f1b843e6ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I7(0xe6, 0x43, 0xb8, 0xf1, 0xc9, 0x45, 0x14));
-}
-
-TEST_F(Append, GeneralLE8Label) {
- Label l;
- section.Append(kLittleEndian, 8, l);
- l = 0xaf48019dfe5c01e5ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I8(0xe5, 0x01, 0x5c, 0xfe, 0x9d, 0x01, 0x48, 0xaf));
-}
-
-TEST_F(Append, GeneralBE1Label) {
- Label l;
- section.Append(kBigEndian, 1, l);
- l = 0xd0ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I1(0xd0));
-}
-
-TEST_F(Append, GeneralBE2Label) {
- Label l;
- section.Append(kBigEndian, 2, l);
- l = 0x2e7eULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2e, 0x7e));
-}
-
-TEST_F(Append, GeneralBE3Label) {
- Label l;
- section.Append(kBigEndian, 3, l);
- l = 0x37dad6ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x37, 0xda, 0xd6));
-}
-
-TEST_F(Append, GeneralBE4Label) {
- Label l;
- section.Append(kBigEndian, 4, l);
- l = 0x715935c7ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I4(0x71, 0x59, 0x35, 0xc7));
-}
-
-TEST_F(Append, GeneralBE5Label) {
- Label l;
- section.Append(kBigEndian, 5, l);
- l = 0x42baeb02b7ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x42, 0xba, 0xeb, 0x02, 0xb7));
-}
-
-TEST_F(Append, GeneralBE6Label) {
- Label l;
- section.Append(kBigEndian, 6, l);
- l = 0xf1cdf10e7b18ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I6(0xf1, 0xcd, 0xf1, 0x0e, 0x7b, 0x18));
-}
-
-TEST_F(Append, GeneralBE7Label) {
- Label l;
- section.Append(kBigEndian, 7, l);
- l = 0xf50a724f0b0d20ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I7(0xf5, 0x0a, 0x72, 0x4f, 0x0b, 0x0d, 0x20));
-}
-
-TEST_F(Append, GeneralBE8Label) {
- Label l;
- section.Append(kBigEndian, 8, l);
- l = 0xa6b2cb5e98dc9c16ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I8(0xa6, 0xb2, 0xcb, 0x5e, 0x98, 0xdc, 0x9c, 0x16));
-}
-
-TEST_F(Append, B8) {
- section.Append(1, 0x2a);
- section.B8(0xd3U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0xd3));
-}
-
-TEST_F(Append, B8Label) {
- Label l;
- section.Append(1, 0x2a);
- section.B8(l);
- l = 0x4bU;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0x4b));
-}
-
-TEST_F(Append, B16) {
- section.Append(1, 0x2a);
- section.B16(0x472aU);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x47, 0x2a));
-}
-
-TEST_F(Append, B16Label) {
- Label l;
- section.Append(1, 0x2a);
- section.B16(l);
- l = 0x55e8U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x55, 0xe8));
-}
-
-TEST_F(Append, B32) {
- section.Append(1, 0x2a);
- section.B32(0xbd412cbcU);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0xbd, 0x41, 0x2c, 0xbc));
-}
-
-TEST_F(Append, B32Label) {
- Label l;
- section.Append(1, 0x2a);
- section.B32(l);
- l = 0x208e37d5U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0x20, 0x8e, 0x37, 0xd5));
-}
-
-TEST_F(Append, B64) {
- section.Append(1, 0x2a);
- section.B64(0x3402a013111e68adULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0x34, 0x02, 0xa0, 0x13, 0x11, 0x1e, 0x68, 0xad));
-}
-
-TEST_F(Append, B64Label) {
- Label l;
- section.Append(1, 0x2a);
- section.B64(l);
- l = 0x355dbfbb4ac6d57fULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0x35, 0x5d, 0xbf, 0xbb, 0x4a, 0xc6, 0xd5, 0x7f));
-}
-
-TEST_F(Append, L8) {
- section.Append(1, 0x2a);
- section.L8(0x26U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0x26));
-}
-
-TEST_F(Append, L8Label) {
- Label l;
- section.Append(1, 0x2a);
- section.L8(l);
- l = 0xa8U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0xa8));
-}
-
-TEST_F(Append, L16) {
- section.Append(1, 0x2a);
- section.L16(0xca6dU);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x6d, 0xca));
-}
-
-TEST_F(Append, L16Label) {
- Label l;
- section.Append(1, 0x2a);
- section.L16(l);
- l = 0xd21fU;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x1f, 0xd2));
-}
-
-TEST_F(Append, L32) {
- section.Append(1, 0x2a);
- section.L32(0x558f6181U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0x81, 0x61, 0x8f, 0x55));
-}
-
-TEST_F(Append, L32Label) {
- Label l;
- section.Append(1, 0x2a);
- section.L32(l);
- l = 0x4b810f82U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0x82, 0x0f, 0x81, 0x4b));
-}
-
-TEST_F(Append, L64) {
- section.Append(1, 0x2a);
- section.L64(0x564384f7579515bfULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0xbf, 0x15, 0x95, 0x57, 0xf7, 0x84, 0x43, 0x56));
-}
-
-TEST_F(Append, L64Label) {
- Label l;
- section.Append(1, 0x2a);
- section.L64(l);
- l = 0x424b1d020667c8dbULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0xdb, 0xc8, 0x67, 0x06, 0x02, 0x1d, 0x4b, 0x42));
-}
-
-TEST_F(Append, D8Big) {
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D8(0xe6U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0xe6));
-}
-
-TEST_F(Append, D8BigLabel) {
- Label l;
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D8(l);
- l = 0xeeU;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0xee));
-}
-
-TEST_F(Append, D16Big) {
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D16(0x83b1U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x83, 0xb1));
-}
-
-TEST_F(Append, D16BigLabel) {
- Label l;
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D16(l);
- l = 0x5b55U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x5b, 0x55));
-}
-
-TEST_F(Append, D32Big) {
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D32(0xd0b0e431U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0xd0, 0xb0, 0xe4, 0x31));
-}
-
-TEST_F(Append, D32BigLabel) {
- Label l;
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D32(l);
- l = 0x312fb340U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0x31, 0x2f, 0xb3, 0x40));
-}
-
-TEST_F(Append, D64Big) {
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D64(0xb109843500dbcb16ULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0xb1, 0x09, 0x84, 0x35, 0x00, 0xdb, 0xcb, 0x16));
-}
-
-TEST_F(Append, D64BigLabel) {
- Label l;
- section.set_endianness(kBigEndian);
- section.Append(1, 0x2a);
- section.D64(l);
- l = 0x9a0d61b70f671fd7ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0x9a, 0x0d, 0x61, 0xb7, 0x0f, 0x67, 0x1f, 0xd7));
-}
-
-TEST_F(Append, D8Little) {
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D8(0x42U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0x42));
-}
-
-TEST_F(Append, D8LittleLabel) {
- Label l;
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D8(l);
- l = 0x05U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I2(0x2a, 0x05));
-}
-
-TEST_F(Append, D16Little) {
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D16(0xc5c5U);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0xc5, 0xc5));
-}
-
-TEST_F(Append, D16LittleLabel) {
- Label l;
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D16(l);
- l = 0xb620U;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I3(0x2a, 0x20, 0xb6));
-}
-
-TEST_F(Append, D32Little) {
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D32(0x1a87d0feU);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0xfe, 0xd0, 0x87, 0x1a));
-}
-
-TEST_F(Append, D32LittleLabel) {
- Label l;
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D32(l);
- l = 0xb8012d6bU;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I5(0x2a, 0x6b, 0x2d, 0x01, 0xb8));
-}
-
-TEST_F(Append, D64Little) {
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D64(0x42de75c61375a1deULL);
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0xde, 0xa1, 0x75, 0x13, 0xc6, 0x75, 0xde, 0x42));
-}
-
-TEST_F(Append, D64LittleLabel) {
- Label l;
- section.set_endianness(kLittleEndian);
- section.Append(1, 0x2a);
- section.D64(l);
- l = 0x8b3bececf3fb5312ULL;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents,
- I9(0x2a, 0x12, 0x53, 0xfb, 0xf3, 0xec, 0xec, 0x3b, 0x8b));
-}
-
-TEST_F(Append, Variety) {
- Label a, b, c, d, e, f, g, h;
- section.Append(kBigEndian, 1, a)
- .Append(kLittleEndian, 8, h)
- .Append(kBigEndian, 1, 0x8bULL)
- .Append(kLittleEndian, 8, 0x0ea56540448f4439ULL)
- .Append(kBigEndian, 2, b)
- .Append(kLittleEndian, 7, g)
- .Append(kBigEndian, 2, 0xcf15ULL)
- .Append(kLittleEndian, 7, 0x29694f04c5724aULL)
- .Append(kBigEndian, 3, c)
- .Append(kLittleEndian, 6, f)
- .Append(kBigEndian, 3, 0x8c3ffdULL)
- .Append(kLittleEndian, 6, 0x6f11ba80187aULL)
- .Append(kBigEndian, 4, d)
- .Append(kLittleEndian, 5, e)
- .Append(kBigEndian, 4, 0x2fda2472ULL)
- .Append(kLittleEndian, 5, 0x0aa02d423fULL)
- .Append(kBigEndian, 5, e)
- .Append(kLittleEndian, 4, d)
- .Append(kBigEndian, 5, 0x53ba432138ULL)
- .Append(kLittleEndian, 4, 0xf139ae60ULL)
- .Append(kBigEndian, 6, f)
- .Append(kLittleEndian, 3, c)
- .Append(kBigEndian, 6, 0x168e436af716ULL)
- .Append(kLittleEndian, 3, 0x3ef189ULL)
- .Append(kBigEndian, 7, g)
- .Append(kLittleEndian, 2, b)
- .Append(kBigEndian, 7, 0xacd4ef233e47d9ULL)
- .Append(kLittleEndian, 2, 0x5311ULL)
- .Append(kBigEndian, 8, h)
- .Append(kLittleEndian, 1, a)
- .Append(kBigEndian, 8, 0x4668d5f1c93637a1ULL)
- .Append(kLittleEndian, 1, 0x65ULL);
- a = 0x79ac9bd8aa256b35ULL;
- b = 0x22d13097ef86c91cULL;
- c = 0xf204968b0a05862fULL;
- d = 0x163177f15a0eb4ecULL;
- e = 0xbd1b0f1d977f2246ULL;
- f = 0x2b0842eee83c6461ULL;
- g = 0x92f4b928a4bf875eULL;
- h = 0x61a199a8f7286ba6ULL;
- ASSERT_EQ(8 * 18U, section.Size());
- ASSERT_TRUE(section.GetContents(&contents));
-
- static const uint8_t expected[] = {
- 0x35, 0xa6, 0x6b, 0x28, 0xf7, 0xa8, 0x99, 0xa1, 0x61,
- 0x8b, 0x39, 0x44, 0x8f, 0x44, 0x40, 0x65, 0xa5, 0x0e,
- 0xc9, 0x1c, 0x5e, 0x87, 0xbf, 0xa4, 0x28, 0xb9, 0xf4,
- 0xcf, 0x15, 0x4a, 0x72, 0xc5, 0x04, 0x4f, 0x69, 0x29,
- 0x05, 0x86, 0x2f, 0x61, 0x64, 0x3c, 0xe8, 0xee, 0x42,
- 0x8c, 0x3f, 0xfd, 0x7a, 0x18, 0x80, 0xba, 0x11, 0x6f,
- 0x5a, 0x0e, 0xb4, 0xec, 0x46, 0x22, 0x7f, 0x97, 0x1d,
- 0x2f, 0xda, 0x24, 0x72, 0x3f, 0x42, 0x2d, 0xa0, 0x0a,
- 0x1d, 0x97, 0x7f, 0x22, 0x46, 0xec, 0xb4, 0x0e, 0x5a,
- 0x53, 0xba, 0x43, 0x21, 0x38, 0x60, 0xae, 0x39, 0xf1,
- 0x42, 0xee, 0xe8, 0x3c, 0x64, 0x61, 0x2f, 0x86, 0x05,
- 0x16, 0x8e, 0x43, 0x6a, 0xf7, 0x16, 0x89, 0xf1, 0x3e,
- 0xf4, 0xb9, 0x28, 0xa4, 0xbf, 0x87, 0x5e, 0x1c, 0xc9,
- 0xac, 0xd4, 0xef, 0x23, 0x3e, 0x47, 0xd9, 0x11, 0x53,
- 0x61, 0xa1, 0x99, 0xa8, 0xf7, 0x28, 0x6b, 0xa6, 0x35,
- 0x46, 0x68, 0xd5, 0xf1, 0xc9, 0x36, 0x37, 0xa1, 0x65,
- };
-
- ASSERT_TRUE(0 == memcmp(contents.data(), expected, sizeof(expected)));
-}
-
-TEST_F(Append, Section) {
- section.Append("murder");
- {
- Section middle;
- middle.Append(" she");
- section.Append(middle);
- }
- section.Append(" wrote");
- EXPECT_EQ(16U, section.Size());
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_STREQ(contents.c_str(), "murder she wrote");
-}
-
-TEST_F(Append, SectionRefs) {
- section.Append("sugar ");
- Label l;
- {
- Section middle;
- Label m;
- middle.B32(m);
- section.Append(middle);
- m = 0x66726565;
- }
- section.Append(" jazz");
- EXPECT_EQ(15U, section.Size());
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_STREQ(contents.c_str(), "sugar free jazz");
-}
-
-TEST_F(Append, LEB128_0) {
- section.LEB128(0);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\0", 1), contents);
-}
-
-TEST_F(Append, LEB128_0x3f) {
- section.LEB128(0x3f);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x3f", 1), contents);
-}
-
-TEST_F(Append, LEB128_0x40) {
- section.LEB128(0x40);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xc0\x00", 2), contents);
-}
-
-TEST_F(Append, LEB128_0x7f) {
- section.LEB128(0x7f);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x00", 2), contents);
-}
-
-TEST_F(Append, LEB128_0x80) {
- section.LEB128(0x80);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x01", 2), contents);
-}
-
-TEST_F(Append, LEB128_0xff) {
- section.LEB128(0xff);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x01", 2), contents);
-}
-
-TEST_F(Append, LEB128_0x1fff) {
- section.LEB128(0x1fff);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x3f", 2), contents);
-}
-
-TEST_F(Append, LEB128_0x2000) {
- section.LEB128(0x2000);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\xc0\x00", 3), contents);
-}
-
-TEST_F(Append, LEB128_n1) {
- section.LEB128(-1);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x7f", 1), contents);
-}
-
-TEST_F(Append, LEB128_n0x40) {
- section.LEB128(-0x40);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x40", 1), contents);
-}
-
-TEST_F(Append, LEB128_n0x41) {
- section.LEB128(-0x41);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xbf\x7f", 2), contents);
-}
-
-TEST_F(Append, LEB128_n0x7f) {
- section.LEB128(-0x7f);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x81\x7f", 2), contents);
-}
-
-TEST_F(Append, LEB128_n0x80) {
- section.LEB128(-0x80);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x7f", 2), contents);
-}
-
-TEST_F(Append, LEB128_n0x2000) {
- section.LEB128(-0x2000);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x40", 2), contents);
-}
-
-TEST_F(Append, LEB128_n0x2001) {
- section.LEB128(-0x2001);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\xbf\x7f", 3), contents);
-}
-
-TEST_F(Append,ULEB128_0) {
- section.ULEB128(0);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\0", 1), contents);
-}
-
-TEST_F(Append,ULEB128_1) {
- section.ULEB128(1);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x01", 1), contents);
-}
-
-TEST_F(Append,ULEB128_0x3f) {
- section.ULEB128(0x3f);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x3f", 1), contents);
-}
-
-TEST_F(Append,ULEB128_0x40) {
- section.ULEB128(0x40);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x40", 1), contents);
-}
-
-TEST_F(Append,ULEB128_0x7f) {
- section.ULEB128(0x7f);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x7f", 1), contents);
-}
-
-TEST_F(Append,ULEB128_0x80) {
- section.ULEB128(0x80);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x01", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0xff) {
- section.ULEB128(0xff);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x01", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0x100) {
- section.ULEB128(0x100);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x02", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0x1fff) {
- section.ULEB128(0x1fff);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x3f", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0x2000) {
- section.ULEB128(0x2000);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x40", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0x3fff) {
- section.ULEB128(0x3fff);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xff\x7f", 2), contents);
-}
-
-TEST_F(Append,ULEB128_0x4000) {
- section.ULEB128(0x4000);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x80\x01", 3), contents);
-}
-
-TEST_F(Append,ULEB128_12857) {
- section.ULEB128(12857);
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\xb9\x64", 2), contents);
-}
-
-TEST_F(Append, LEBChain) {
- section.LEB128(-0x80).ULEB128(12857).Append("*");
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(string("\x80\x7f\xb9\x64*", 5), contents);
-}
-
-
-class GetContents: public SectionFixture, public Test { };
-
-TEST_F(GetContents, Undefined) {
- Label l;
- section.Append(kLittleEndian, 8, l);
- ASSERT_FALSE(section.GetContents(&contents));
-}
-
-TEST_F(GetContents, ClearsContents) {
- section.Append((size_t) 10, '*');
- EXPECT_EQ(10U, section.Size());
- EXPECT_TRUE(section.GetContents(&contents));
- EXPECT_EQ(0U, section.Size());
-}
-
-TEST_F(GetContents, ClearsReferences) {
- Label l;
- section.Append(kBigEndian, 1, l);
- l = 42;
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_BYTES(contents, I1(42));
- ASSERT_TRUE(section.GetContents(&contents)); // should not die
-}
-
-class Miscellanea: public SectionFixture, public Test { };
-
-TEST_F(Miscellanea, Clear) {
- section.Append("howdy");
- Label l;
- section.L32(l);
- EXPECT_EQ(9U, section.Size());
- section.Clear();
- EXPECT_EQ(0U, section.Size());
- l = 0x8d231bf0U;
- ASSERT_TRUE(section.GetContents(&contents)); // should not die
-}
-
-TEST_F(Miscellanea, Align) {
- section.Append("*");
- EXPECT_EQ(1U, section.Size());
- section.Align(4).Append("*");
- EXPECT_EQ(5U, section.Size());
- section.Append("*").Align(2);
- EXPECT_EQ(6U, section.Size());
-}
-
-TEST_F(Miscellanea, AlignPad) {
- section.Append("*");
- EXPECT_EQ(1U, section.Size());
- section.Align(4, ' ').Append("*");
- EXPECT_EQ(5U, section.Size());
- section.Append("*").Align(2, ' ');
- EXPECT_EQ(6U, section.Size());
- ASSERT_TRUE(section.GetContents(&contents));
- ASSERT_EQ(string("* **"), contents);
-}
-
-TEST_F(Miscellanea, StartHereMark) {
- Label m;
- section.Append(42, ' ').Mark(&m).Append(13, '+');
- EXPECT_EQ(42U, m - section.start());
- EXPECT_EQ(42U + 13U, section.Here() - section.start());
- EXPECT_FALSE(section.start().IsKnownConstant());
- EXPECT_FALSE(m.IsKnownConstant());
- EXPECT_FALSE(section.Here().IsKnownConstant());
-}
-
-TEST_F(Miscellanea, Endianness) {
- section.set_endianness(kBigEndian);
- EXPECT_EQ(kBigEndian, section.endianness());
- section.set_endianness(kLittleEndian);
- EXPECT_EQ(kLittleEndian, section.endianness());
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/testdata/func-line-pairing.h b/toolkit/crashreporter/google-breakpad/src/common/testdata/func-line-pairing.h
deleted file mode 100644
index 05538f961..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/testdata/func-line-pairing.h
+++ /dev/null
@@ -1,676 +0,0 @@
-// -*- mode: c++ -*-
-
-// Test data for pairing functions and lines.
-//
-// For a pair of functions that are adjacent (10,20),(20,25) and a
-// pair that are not (10,15),(20,25), we include a test case for every
-// possible arrangement of two lines relative to those functions. We
-// include cases only for non-empty ranges, since empty functions and
-// lines are dropped before we do any pairing.
-//
-// Each test case is represented by a macro call of the form:
-//
-// PAIRING(func1_start, func1_end, func2_start, func2_end,
-// line1_start, line1_end, line2_start, line2_end,
-// func1_num_lines, func2_num_lines,
-// func1_line1_start, func1_line1_end,
-// func1_line2_start, func1_line2_end,
-// func2_line1_start, func2_line1_end,
-// func2_line2_start, func2_line2_end,
-// uncovered_funcs, uncovered_lines)
-//
-// where:
-// - funcN_{start,end} is the range of the N'th function
-// - lineN_{start,end} is the range of the N'th function
-// - funcN_num_lines is the number of source lines that should be
-// paired with the N'th function
-// - funcN_lineM_{start,end} is the range of the M'th line
-// paired with the N'th function, where 0,0 indicates that
-// there should be no such line paired
-// - uncovered_funcs is the number of functions with area that is
-// uncovered by any line, and
-// - uncovered_lines is the reverse.
-
-// func1 func2 line1 line2 num pairing1 pairing2 uncovered
-PAIRING(10, 20, 20, 25, 6, 7, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #0
-PAIRING(10, 20, 20, 25, 6, 7, 7, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #1
-PAIRING(10, 20, 20, 25, 6, 7, 7, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #2
-PAIRING(10, 20, 20, 25, 6, 7, 7, 20, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 2) // #3
-PAIRING(10, 20, 20, 25, 6, 7, 7, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 2) // #4
-PAIRING(10, 20, 20, 25, 6, 7, 7, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #5
-PAIRING(10, 20, 20, 25, 6, 7, 7, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #6
-PAIRING(10, 20, 20, 25, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #7
-PAIRING(10, 20, 20, 25, 6, 7, 8, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #8
-PAIRING(10, 20, 20, 25, 6, 7, 8, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #9
-PAIRING(10, 20, 20, 25, 6, 7, 8, 20, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 2) // #10
-PAIRING(10, 20, 20, 25, 6, 7, 8, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 2) // #11
-PAIRING(10, 20, 20, 25, 6, 7, 8, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #12
-PAIRING(10, 20, 20, 25, 6, 7, 8, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #13
-PAIRING(10, 20, 20, 25, 6, 7, 10, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #14
-PAIRING(10, 20, 20, 25, 6, 7, 10, 20, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 1) // #15
-PAIRING(10, 20, 20, 25, 6, 7, 10, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 1) // #16
-PAIRING(10, 20, 20, 25, 6, 7, 10, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #17
-PAIRING(10, 20, 20, 25, 6, 7, 10, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #18
-PAIRING(10, 20, 20, 25, 6, 7, 11, 12, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #19
-PAIRING(10, 20, 20, 25, 6, 7, 11, 20, 1, 0, 11, 20, 0, 0, 0, 0, 0, 0, 2, 1) // #20
-PAIRING(10, 20, 20, 25, 6, 7, 11, 21, 1, 1, 11, 20, 0, 0, 20, 21, 0, 0, 2, 1) // #21
-PAIRING(10, 20, 20, 25, 6, 7, 11, 25, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 1) // #22
-PAIRING(10, 20, 20, 25, 6, 7, 11, 26, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 2) // #23
-PAIRING(10, 20, 20, 25, 6, 7, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #24
-PAIRING(10, 20, 20, 25, 6, 7, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #25
-PAIRING(10, 20, 20, 25, 6, 7, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #26
-PAIRING(10, 20, 20, 25, 6, 7, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #27
-PAIRING(10, 20, 20, 25, 6, 7, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #28
-PAIRING(10, 20, 20, 25, 6, 7, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #29
-PAIRING(10, 20, 20, 25, 6, 7, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #30
-PAIRING(10, 20, 20, 25, 6, 7, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #31
-PAIRING(10, 20, 20, 25, 6, 10, 10, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #32
-PAIRING(10, 20, 20, 25, 6, 10, 10, 20, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 1) // #33
-PAIRING(10, 20, 20, 25, 6, 10, 10, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 1) // #34
-PAIRING(10, 20, 20, 25, 6, 10, 10, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #35
-PAIRING(10, 20, 20, 25, 6, 10, 10, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #36
-PAIRING(10, 20, 20, 25, 6, 10, 11, 12, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #37
-PAIRING(10, 20, 20, 25, 6, 10, 11, 20, 1, 0, 11, 20, 0, 0, 0, 0, 0, 0, 2, 1) // #38
-PAIRING(10, 20, 20, 25, 6, 10, 11, 21, 1, 1, 11, 20, 0, 0, 20, 21, 0, 0, 2, 1) // #39
-PAIRING(10, 20, 20, 25, 6, 10, 11, 25, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 1) // #40
-PAIRING(10, 20, 20, 25, 6, 10, 11, 26, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 2) // #41
-PAIRING(10, 20, 20, 25, 6, 10, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #42
-PAIRING(10, 20, 20, 25, 6, 10, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #43
-PAIRING(10, 20, 20, 25, 6, 10, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #44
-PAIRING(10, 20, 20, 25, 6, 10, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #45
-PAIRING(10, 20, 20, 25, 6, 10, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #46
-PAIRING(10, 20, 20, 25, 6, 10, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #47
-PAIRING(10, 20, 20, 25, 6, 10, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #48
-PAIRING(10, 20, 20, 25, 6, 10, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #49
-PAIRING(10, 20, 20, 25, 6, 11, 11, 12, 2, 0, 10, 11, 11, 12, 0, 0, 0, 0, 2, 1) // #50
-PAIRING(10, 20, 20, 25, 6, 11, 11, 20, 2, 0, 10, 11, 11, 20, 0, 0, 0, 0, 1, 1) // #51
-PAIRING(10, 20, 20, 25, 6, 11, 11, 21, 2, 1, 10, 11, 11, 20, 20, 21, 0, 0, 1, 1) // #52
-PAIRING(10, 20, 20, 25, 6, 11, 11, 25, 2, 1, 10, 11, 11, 20, 20, 25, 0, 0, 0, 1) // #53
-PAIRING(10, 20, 20, 25, 6, 11, 11, 26, 2, 1, 10, 11, 11, 20, 20, 25, 0, 0, 0, 2) // #54
-PAIRING(10, 20, 20, 25, 6, 11, 12, 13, 2, 0, 10, 11, 12, 13, 0, 0, 0, 0, 2, 1) // #55
-PAIRING(10, 20, 20, 25, 6, 11, 12, 20, 2, 0, 10, 11, 12, 20, 0, 0, 0, 0, 2, 1) // #56
-PAIRING(10, 20, 20, 25, 6, 11, 12, 21, 2, 1, 10, 11, 12, 20, 20, 21, 0, 0, 2, 1) // #57
-PAIRING(10, 20, 20, 25, 6, 11, 12, 25, 2, 1, 10, 11, 12, 20, 20, 25, 0, 0, 1, 1) // #58
-PAIRING(10, 20, 20, 25, 6, 11, 12, 26, 2, 1, 10, 11, 12, 20, 20, 25, 0, 0, 1, 2) // #59
-PAIRING(10, 20, 20, 25, 6, 11, 20, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 1) // #60
-PAIRING(10, 20, 20, 25, 6, 11, 20, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #61
-PAIRING(10, 20, 20, 25, 6, 11, 20, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #62
-PAIRING(10, 20, 20, 25, 6, 11, 21, 22, 1, 1, 10, 11, 0, 0, 21, 22, 0, 0, 2, 1) // #63
-PAIRING(10, 20, 20, 25, 6, 11, 21, 25, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 1) // #64
-PAIRING(10, 20, 20, 25, 6, 11, 21, 26, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 2) // #65
-PAIRING(10, 20, 20, 25, 6, 11, 25, 26, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #66
-PAIRING(10, 20, 20, 25, 6, 11, 26, 27, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #67
-PAIRING(10, 20, 20, 25, 6, 20, 20, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 1) // #68
-PAIRING(10, 20, 20, 25, 6, 20, 20, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #69
-PAIRING(10, 20, 20, 25, 6, 20, 20, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #70
-PAIRING(10, 20, 20, 25, 6, 20, 21, 22, 1, 1, 10, 20, 0, 0, 21, 22, 0, 0, 1, 1) // #71
-PAIRING(10, 20, 20, 25, 6, 20, 21, 25, 1, 1, 10, 20, 0, 0, 21, 25, 0, 0, 1, 1) // #72
-PAIRING(10, 20, 20, 25, 6, 20, 21, 26, 1, 1, 10, 20, 0, 0, 21, 25, 0, 0, 1, 2) // #73
-PAIRING(10, 20, 20, 25, 6, 20, 25, 26, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 2) // #74
-PAIRING(10, 20, 20, 25, 6, 20, 26, 27, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 2) // #75
-PAIRING(10, 20, 20, 25, 6, 21, 21, 22, 1, 2, 10, 20, 0, 0, 20, 21, 21, 22, 1, 1) // #76
-PAIRING(10, 20, 20, 25, 6, 21, 21, 25, 1, 2, 10, 20, 0, 0, 20, 21, 21, 25, 0, 1) // #77
-PAIRING(10, 20, 20, 25, 6, 21, 21, 26, 1, 2, 10, 20, 0, 0, 20, 21, 21, 25, 0, 2) // #78
-PAIRING(10, 20, 20, 25, 6, 21, 22, 23, 1, 2, 10, 20, 0, 0, 20, 21, 22, 23, 1, 1) // #79
-PAIRING(10, 20, 20, 25, 6, 21, 22, 25, 1, 2, 10, 20, 0, 0, 20, 21, 22, 25, 1, 1) // #80
-PAIRING(10, 20, 20, 25, 6, 21, 22, 26, 1, 2, 10, 20, 0, 0, 20, 21, 22, 25, 1, 2) // #81
-PAIRING(10, 20, 20, 25, 6, 21, 25, 26, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 2) // #82
-PAIRING(10, 20, 20, 25, 6, 21, 26, 27, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 2) // #83
-PAIRING(10, 20, 20, 25, 6, 25, 25, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #84
-PAIRING(10, 20, 20, 25, 6, 25, 26, 27, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #85
-PAIRING(10, 20, 20, 25, 6, 26, 26, 27, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #86
-PAIRING(10, 20, 20, 25, 6, 26, 27, 28, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #87
-PAIRING(10, 20, 20, 25, 10, 11, 11, 12, 2, 0, 10, 11, 11, 12, 0, 0, 0, 0, 2, 0) // #88
-PAIRING(10, 20, 20, 25, 10, 11, 11, 20, 2, 0, 10, 11, 11, 20, 0, 0, 0, 0, 1, 0) // #89
-PAIRING(10, 20, 20, 25, 10, 11, 11, 21, 2, 1, 10, 11, 11, 20, 20, 21, 0, 0, 1, 0) // #90
-PAIRING(10, 20, 20, 25, 10, 11, 11, 25, 2, 1, 10, 11, 11, 20, 20, 25, 0, 0, 0, 0) // #91
-PAIRING(10, 20, 20, 25, 10, 11, 11, 26, 2, 1, 10, 11, 11, 20, 20, 25, 0, 0, 0, 1) // #92
-PAIRING(10, 20, 20, 25, 10, 11, 12, 13, 2, 0, 10, 11, 12, 13, 0, 0, 0, 0, 2, 0) // #93
-PAIRING(10, 20, 20, 25, 10, 11, 12, 20, 2, 0, 10, 11, 12, 20, 0, 0, 0, 0, 2, 0) // #94
-PAIRING(10, 20, 20, 25, 10, 11, 12, 21, 2, 1, 10, 11, 12, 20, 20, 21, 0, 0, 2, 0) // #95
-PAIRING(10, 20, 20, 25, 10, 11, 12, 25, 2, 1, 10, 11, 12, 20, 20, 25, 0, 0, 1, 0) // #96
-PAIRING(10, 20, 20, 25, 10, 11, 12, 26, 2, 1, 10, 11, 12, 20, 20, 25, 0, 0, 1, 1) // #97
-PAIRING(10, 20, 20, 25, 10, 11, 20, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 0) // #98
-PAIRING(10, 20, 20, 25, 10, 11, 20, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 0) // #99
-PAIRING(10, 20, 20, 25, 10, 11, 20, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #100
-PAIRING(10, 20, 20, 25, 10, 11, 21, 22, 1, 1, 10, 11, 0, 0, 21, 22, 0, 0, 2, 0) // #101
-PAIRING(10, 20, 20, 25, 10, 11, 21, 25, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 0) // #102
-PAIRING(10, 20, 20, 25, 10, 11, 21, 26, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 1) // #103
-PAIRING(10, 20, 20, 25, 10, 11, 25, 26, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #104
-PAIRING(10, 20, 20, 25, 10, 11, 26, 27, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #105
-PAIRING(10, 20, 20, 25, 10, 20, 20, 21, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 0) // #106
-PAIRING(10, 20, 20, 25, 10, 20, 20, 25, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 0) // #107
-PAIRING(10, 20, 20, 25, 10, 20, 20, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #108
-PAIRING(10, 20, 20, 25, 10, 20, 21, 22, 1, 1, 10, 20, 0, 0, 21, 22, 0, 0, 1, 0) // #109
-PAIRING(10, 20, 20, 25, 10, 20, 21, 25, 1, 1, 10, 20, 0, 0, 21, 25, 0, 0, 1, 0) // #110
-PAIRING(10, 20, 20, 25, 10, 20, 21, 26, 1, 1, 10, 20, 0, 0, 21, 25, 0, 0, 1, 1) // #111
-PAIRING(10, 20, 20, 25, 10, 20, 25, 26, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 1) // #112
-PAIRING(10, 20, 20, 25, 10, 20, 26, 27, 1, 0, 10, 20, 0, 0, 0, 0, 0, 0, 1, 1) // #113
-PAIRING(10, 20, 20, 25, 10, 21, 21, 22, 1, 2, 10, 20, 0, 0, 20, 21, 21, 22, 1, 0) // #114
-PAIRING(10, 20, 20, 25, 10, 21, 21, 25, 1, 2, 10, 20, 0, 0, 20, 21, 21, 25, 0, 0) // #115
-PAIRING(10, 20, 20, 25, 10, 21, 21, 26, 1, 2, 10, 20, 0, 0, 20, 21, 21, 25, 0, 1) // #116
-PAIRING(10, 20, 20, 25, 10, 21, 22, 23, 1, 2, 10, 20, 0, 0, 20, 21, 22, 23, 1, 0) // #117
-PAIRING(10, 20, 20, 25, 10, 21, 22, 25, 1, 2, 10, 20, 0, 0, 20, 21, 22, 25, 1, 0) // #118
-PAIRING(10, 20, 20, 25, 10, 21, 22, 26, 1, 2, 10, 20, 0, 0, 20, 21, 22, 25, 1, 1) // #119
-PAIRING(10, 20, 20, 25, 10, 21, 25, 26, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 1) // #120
-PAIRING(10, 20, 20, 25, 10, 21, 26, 27, 1, 1, 10, 20, 0, 0, 20, 21, 0, 0, 1, 1) // #121
-PAIRING(10, 20, 20, 25, 10, 25, 25, 26, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #122
-PAIRING(10, 20, 20, 25, 10, 25, 26, 27, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 1) // #123
-PAIRING(10, 20, 20, 25, 10, 26, 26, 27, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #124
-PAIRING(10, 20, 20, 25, 10, 26, 27, 28, 1, 1, 10, 20, 0, 0, 20, 25, 0, 0, 0, 2) // #125
-PAIRING(10, 20, 20, 25, 11, 12, 12, 13, 2, 0, 11, 12, 12, 13, 0, 0, 0, 0, 2, 0) // #126
-PAIRING(10, 20, 20, 25, 11, 12, 12, 20, 2, 0, 11, 12, 12, 20, 0, 0, 0, 0, 2, 0) // #127
-PAIRING(10, 20, 20, 25, 11, 12, 12, 21, 2, 1, 11, 12, 12, 20, 20, 21, 0, 0, 2, 0) // #128
-PAIRING(10, 20, 20, 25, 11, 12, 12, 25, 2, 1, 11, 12, 12, 20, 20, 25, 0, 0, 1, 0) // #129
-PAIRING(10, 20, 20, 25, 11, 12, 12, 26, 2, 1, 11, 12, 12, 20, 20, 25, 0, 0, 1, 1) // #130
-PAIRING(10, 20, 20, 25, 11, 12, 13, 14, 2, 0, 11, 12, 13, 14, 0, 0, 0, 0, 2, 0) // #131
-PAIRING(10, 20, 20, 25, 11, 12, 13, 20, 2, 0, 11, 12, 13, 20, 0, 0, 0, 0, 2, 0) // #132
-PAIRING(10, 20, 20, 25, 11, 12, 13, 21, 2, 1, 11, 12, 13, 20, 20, 21, 0, 0, 2, 0) // #133
-PAIRING(10, 20, 20, 25, 11, 12, 13, 25, 2, 1, 11, 12, 13, 20, 20, 25, 0, 0, 1, 0) // #134
-PAIRING(10, 20, 20, 25, 11, 12, 13, 26, 2, 1, 11, 12, 13, 20, 20, 25, 0, 0, 1, 1) // #135
-PAIRING(10, 20, 20, 25, 11, 12, 20, 21, 1, 1, 11, 12, 0, 0, 20, 21, 0, 0, 2, 0) // #136
-PAIRING(10, 20, 20, 25, 11, 12, 20, 25, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 0) // #137
-PAIRING(10, 20, 20, 25, 11, 12, 20, 26, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #138
-PAIRING(10, 20, 20, 25, 11, 12, 21, 22, 1, 1, 11, 12, 0, 0, 21, 22, 0, 0, 2, 0) // #139
-PAIRING(10, 20, 20, 25, 11, 12, 21, 25, 1, 1, 11, 12, 0, 0, 21, 25, 0, 0, 2, 0) // #140
-PAIRING(10, 20, 20, 25, 11, 12, 21, 26, 1, 1, 11, 12, 0, 0, 21, 25, 0, 0, 2, 1) // #141
-PAIRING(10, 20, 20, 25, 11, 12, 25, 26, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #142
-PAIRING(10, 20, 20, 25, 11, 12, 26, 27, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #143
-PAIRING(10, 20, 20, 25, 11, 20, 20, 21, 1, 1, 11, 20, 0, 0, 20, 21, 0, 0, 2, 0) // #144
-PAIRING(10, 20, 20, 25, 11, 20, 20, 25, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 0) // #145
-PAIRING(10, 20, 20, 25, 11, 20, 20, 26, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 1) // #146
-PAIRING(10, 20, 20, 25, 11, 20, 21, 22, 1, 1, 11, 20, 0, 0, 21, 22, 0, 0, 2, 0) // #147
-PAIRING(10, 20, 20, 25, 11, 20, 21, 25, 1, 1, 11, 20, 0, 0, 21, 25, 0, 0, 2, 0) // #148
-PAIRING(10, 20, 20, 25, 11, 20, 21, 26, 1, 1, 11, 20, 0, 0, 21, 25, 0, 0, 2, 1) // #149
-PAIRING(10, 20, 20, 25, 11, 20, 25, 26, 1, 0, 11, 20, 0, 0, 0, 0, 0, 0, 2, 1) // #150
-PAIRING(10, 20, 20, 25, 11, 20, 26, 27, 1, 0, 11, 20, 0, 0, 0, 0, 0, 0, 2, 1) // #151
-PAIRING(10, 20, 20, 25, 11, 21, 21, 22, 1, 2, 11, 20, 0, 0, 20, 21, 21, 22, 2, 0) // #152
-PAIRING(10, 20, 20, 25, 11, 21, 21, 25, 1, 2, 11, 20, 0, 0, 20, 21, 21, 25, 1, 0) // #153
-PAIRING(10, 20, 20, 25, 11, 21, 21, 26, 1, 2, 11, 20, 0, 0, 20, 21, 21, 25, 1, 1) // #154
-PAIRING(10, 20, 20, 25, 11, 21, 22, 23, 1, 2, 11, 20, 0, 0, 20, 21, 22, 23, 2, 0) // #155
-PAIRING(10, 20, 20, 25, 11, 21, 22, 25, 1, 2, 11, 20, 0, 0, 20, 21, 22, 25, 2, 0) // #156
-PAIRING(10, 20, 20, 25, 11, 21, 22, 26, 1, 2, 11, 20, 0, 0, 20, 21, 22, 25, 2, 1) // #157
-PAIRING(10, 20, 20, 25, 11, 21, 25, 26, 1, 1, 11, 20, 0, 0, 20, 21, 0, 0, 2, 1) // #158
-PAIRING(10, 20, 20, 25, 11, 21, 26, 27, 1, 1, 11, 20, 0, 0, 20, 21, 0, 0, 2, 1) // #159
-PAIRING(10, 20, 20, 25, 11, 25, 25, 26, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 1) // #160
-PAIRING(10, 20, 20, 25, 11, 25, 26, 27, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 1) // #161
-PAIRING(10, 20, 20, 25, 11, 26, 26, 27, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 2) // #162
-PAIRING(10, 20, 20, 25, 11, 26, 27, 28, 1, 1, 11, 20, 0, 0, 20, 25, 0, 0, 1, 2) // #163
-PAIRING(10, 20, 20, 25, 20, 21, 21, 22, 0, 2, 0, 0, 0, 0, 20, 21, 21, 22, 2, 0) // #164
-PAIRING(10, 20, 20, 25, 20, 21, 21, 25, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 0) // #165
-PAIRING(10, 20, 20, 25, 20, 21, 21, 26, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 1) // #166
-PAIRING(10, 20, 20, 25, 20, 21, 22, 23, 0, 2, 0, 0, 0, 0, 20, 21, 22, 23, 2, 0) // #167
-PAIRING(10, 20, 20, 25, 20, 21, 22, 25, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 0) // #168
-PAIRING(10, 20, 20, 25, 20, 21, 22, 26, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 1) // #169
-PAIRING(10, 20, 20, 25, 20, 21, 25, 26, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #170
-PAIRING(10, 20, 20, 25, 20, 21, 26, 27, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #171
-PAIRING(10, 20, 20, 25, 20, 25, 25, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #172
-PAIRING(10, 20, 20, 25, 20, 25, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #173
-PAIRING(10, 20, 20, 25, 20, 26, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #174
-PAIRING(10, 20, 20, 25, 20, 26, 27, 28, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #175
-PAIRING(10, 20, 20, 25, 21, 22, 22, 23, 0, 2, 0, 0, 0, 0, 21, 22, 22, 23, 2, 0) // #176
-PAIRING(10, 20, 20, 25, 21, 22, 22, 25, 0, 2, 0, 0, 0, 0, 21, 22, 22, 25, 2, 0) // #177
-PAIRING(10, 20, 20, 25, 21, 22, 22, 26, 0, 2, 0, 0, 0, 0, 21, 22, 22, 25, 2, 1) // #178
-PAIRING(10, 20, 20, 25, 21, 22, 23, 24, 0, 2, 0, 0, 0, 0, 21, 22, 23, 24, 2, 0) // #179
-PAIRING(10, 20, 20, 25, 21, 22, 23, 25, 0, 2, 0, 0, 0, 0, 21, 22, 23, 25, 2, 0) // #180
-PAIRING(10, 20, 20, 25, 21, 22, 23, 26, 0, 2, 0, 0, 0, 0, 21, 22, 23, 25, 2, 1) // #181
-PAIRING(10, 20, 20, 25, 21, 22, 25, 26, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #182
-PAIRING(10, 20, 20, 25, 21, 22, 26, 27, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #183
-PAIRING(10, 20, 20, 25, 21, 25, 25, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #184
-PAIRING(10, 20, 20, 25, 21, 25, 26, 27, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #185
-PAIRING(10, 20, 20, 25, 21, 26, 26, 27, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #186
-PAIRING(10, 20, 20, 25, 21, 26, 27, 28, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #187
-PAIRING(10, 20, 20, 25, 25, 26, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #188
-PAIRING(10, 20, 20, 25, 25, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #189
-PAIRING(10, 20, 20, 25, 26, 27, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #190
-PAIRING(10, 20, 20, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #191
-PAIRING(10, 15, 20, 25, 6, 7, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #192
-PAIRING(10, 15, 20, 25, 6, 7, 7, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #193
-PAIRING(10, 15, 20, 25, 6, 7, 7, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #194
-PAIRING(10, 15, 20, 25, 6, 7, 7, 15, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #195
-PAIRING(10, 15, 20, 25, 6, 7, 7, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #196
-PAIRING(10, 15, 20, 25, 6, 7, 7, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #197
-PAIRING(10, 15, 20, 25, 6, 7, 7, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #198
-PAIRING(10, 15, 20, 25, 6, 7, 7, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #199
-PAIRING(10, 15, 20, 25, 6, 7, 7, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #200
-PAIRING(10, 15, 20, 25, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #201
-PAIRING(10, 15, 20, 25, 6, 7, 8, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #202
-PAIRING(10, 15, 20, 25, 6, 7, 8, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #203
-PAIRING(10, 15, 20, 25, 6, 7, 8, 15, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #204
-PAIRING(10, 15, 20, 25, 6, 7, 8, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #205
-PAIRING(10, 15, 20, 25, 6, 7, 8, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #206
-PAIRING(10, 15, 20, 25, 6, 7, 8, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #207
-PAIRING(10, 15, 20, 25, 6, 7, 8, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #208
-PAIRING(10, 15, 20, 25, 6, 7, 8, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #209
-PAIRING(10, 15, 20, 25, 6, 7, 10, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #210
-PAIRING(10, 15, 20, 25, 6, 7, 10, 15, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #211
-PAIRING(10, 15, 20, 25, 6, 7, 10, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #212
-PAIRING(10, 15, 20, 25, 6, 7, 10, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #213
-PAIRING(10, 15, 20, 25, 6, 7, 10, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #214
-PAIRING(10, 15, 20, 25, 6, 7, 10, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #215
-PAIRING(10, 15, 20, 25, 6, 7, 10, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #216
-PAIRING(10, 15, 20, 25, 6, 7, 11, 12, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #217
-PAIRING(10, 15, 20, 25, 6, 7, 11, 15, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #218
-PAIRING(10, 15, 20, 25, 6, 7, 11, 16, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #219
-PAIRING(10, 15, 20, 25, 6, 7, 11, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #220
-PAIRING(10, 15, 20, 25, 6, 7, 11, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #221
-PAIRING(10, 15, 20, 25, 6, 7, 11, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #222
-PAIRING(10, 15, 20, 25, 6, 7, 11, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #223
-PAIRING(10, 15, 20, 25, 6, 7, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #224
-PAIRING(10, 15, 20, 25, 6, 7, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #225
-PAIRING(10, 15, 20, 25, 6, 7, 15, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #226
-PAIRING(10, 15, 20, 25, 6, 7, 15, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #227
-PAIRING(10, 15, 20, 25, 6, 7, 15, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #228
-PAIRING(10, 15, 20, 25, 6, 7, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #229
-PAIRING(10, 15, 20, 25, 6, 7, 16, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #230
-PAIRING(10, 15, 20, 25, 6, 7, 16, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #231
-PAIRING(10, 15, 20, 25, 6, 7, 16, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #232
-PAIRING(10, 15, 20, 25, 6, 7, 16, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #233
-PAIRING(10, 15, 20, 25, 6, 7, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #234
-PAIRING(10, 15, 20, 25, 6, 7, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #235
-PAIRING(10, 15, 20, 25, 6, 7, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #236
-PAIRING(10, 15, 20, 25, 6, 7, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #237
-PAIRING(10, 15, 20, 25, 6, 7, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #238
-PAIRING(10, 15, 20, 25, 6, 7, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #239
-PAIRING(10, 15, 20, 25, 6, 7, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #240
-PAIRING(10, 15, 20, 25, 6, 7, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #241
-PAIRING(10, 15, 20, 25, 6, 10, 10, 11, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #242
-PAIRING(10, 15, 20, 25, 6, 10, 10, 15, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #243
-PAIRING(10, 15, 20, 25, 6, 10, 10, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #244
-PAIRING(10, 15, 20, 25, 6, 10, 10, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #245
-PAIRING(10, 15, 20, 25, 6, 10, 10, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #246
-PAIRING(10, 15, 20, 25, 6, 10, 10, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #247
-PAIRING(10, 15, 20, 25, 6, 10, 10, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #248
-PAIRING(10, 15, 20, 25, 6, 10, 11, 12, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #249
-PAIRING(10, 15, 20, 25, 6, 10, 11, 15, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #250
-PAIRING(10, 15, 20, 25, 6, 10, 11, 16, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #251
-PAIRING(10, 15, 20, 25, 6, 10, 11, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #252
-PAIRING(10, 15, 20, 25, 6, 10, 11, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #253
-PAIRING(10, 15, 20, 25, 6, 10, 11, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #254
-PAIRING(10, 15, 20, 25, 6, 10, 11, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #255
-PAIRING(10, 15, 20, 25, 6, 10, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #256
-PAIRING(10, 15, 20, 25, 6, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #257
-PAIRING(10, 15, 20, 25, 6, 10, 15, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #258
-PAIRING(10, 15, 20, 25, 6, 10, 15, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #259
-PAIRING(10, 15, 20, 25, 6, 10, 15, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #260
-PAIRING(10, 15, 20, 25, 6, 10, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #261
-PAIRING(10, 15, 20, 25, 6, 10, 16, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #262
-PAIRING(10, 15, 20, 25, 6, 10, 16, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #263
-PAIRING(10, 15, 20, 25, 6, 10, 16, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #264
-PAIRING(10, 15, 20, 25, 6, 10, 16, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #265
-PAIRING(10, 15, 20, 25, 6, 10, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #266
-PAIRING(10, 15, 20, 25, 6, 10, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #267
-PAIRING(10, 15, 20, 25, 6, 10, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #268
-PAIRING(10, 15, 20, 25, 6, 10, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #269
-PAIRING(10, 15, 20, 25, 6, 10, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #270
-PAIRING(10, 15, 20, 25, 6, 10, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #271
-PAIRING(10, 15, 20, 25, 6, 10, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #272
-PAIRING(10, 15, 20, 25, 6, 10, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #273
-PAIRING(10, 15, 20, 25, 6, 11, 11, 12, 2, 0, 10, 11, 11, 12, 0, 0, 0, 0, 2, 1) // #274
-PAIRING(10, 15, 20, 25, 6, 11, 11, 15, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 1) // #275
-PAIRING(10, 15, 20, 25, 6, 11, 11, 16, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 2) // #276
-PAIRING(10, 15, 20, 25, 6, 11, 11, 20, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 1) // #277
-PAIRING(10, 15, 20, 25, 6, 11, 11, 21, 2, 1, 10, 11, 11, 15, 20, 21, 0, 0, 1, 2) // #278
-PAIRING(10, 15, 20, 25, 6, 11, 11, 25, 2, 1, 10, 11, 11, 15, 20, 25, 0, 0, 0, 2) // #279
-PAIRING(10, 15, 20, 25, 6, 11, 11, 26, 2, 1, 10, 11, 11, 15, 20, 25, 0, 0, 0, 2) // #280
-PAIRING(10, 15, 20, 25, 6, 11, 12, 13, 2, 0, 10, 11, 12, 13, 0, 0, 0, 0, 2, 1) // #281
-PAIRING(10, 15, 20, 25, 6, 11, 12, 15, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 1) // #282
-PAIRING(10, 15, 20, 25, 6, 11, 12, 16, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 2) // #283
-PAIRING(10, 15, 20, 25, 6, 11, 12, 20, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 1) // #284
-PAIRING(10, 15, 20, 25, 6, 11, 12, 21, 2, 1, 10, 11, 12, 15, 20, 21, 0, 0, 2, 2) // #285
-PAIRING(10, 15, 20, 25, 6, 11, 12, 25, 2, 1, 10, 11, 12, 15, 20, 25, 0, 0, 1, 2) // #286
-PAIRING(10, 15, 20, 25, 6, 11, 12, 26, 2, 1, 10, 11, 12, 15, 20, 25, 0, 0, 1, 2) // #287
-PAIRING(10, 15, 20, 25, 6, 11, 15, 16, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #288
-PAIRING(10, 15, 20, 25, 6, 11, 15, 20, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #289
-PAIRING(10, 15, 20, 25, 6, 11, 15, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 2) // #290
-PAIRING(10, 15, 20, 25, 6, 11, 15, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #291
-PAIRING(10, 15, 20, 25, 6, 11, 15, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #292
-PAIRING(10, 15, 20, 25, 6, 11, 16, 17, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #293
-PAIRING(10, 15, 20, 25, 6, 11, 16, 20, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #294
-PAIRING(10, 15, 20, 25, 6, 11, 16, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 2) // #295
-PAIRING(10, 15, 20, 25, 6, 11, 16, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #296
-PAIRING(10, 15, 20, 25, 6, 11, 16, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #297
-PAIRING(10, 15, 20, 25, 6, 11, 20, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 1) // #298
-PAIRING(10, 15, 20, 25, 6, 11, 20, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #299
-PAIRING(10, 15, 20, 25, 6, 11, 20, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 2) // #300
-PAIRING(10, 15, 20, 25, 6, 11, 21, 22, 1, 1, 10, 11, 0, 0, 21, 22, 0, 0, 2, 1) // #301
-PAIRING(10, 15, 20, 25, 6, 11, 21, 25, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 1) // #302
-PAIRING(10, 15, 20, 25, 6, 11, 21, 26, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 2) // #303
-PAIRING(10, 15, 20, 25, 6, 11, 25, 26, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #304
-PAIRING(10, 15, 20, 25, 6, 11, 26, 27, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 2) // #305
-PAIRING(10, 15, 20, 25, 6, 15, 15, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #306
-PAIRING(10, 15, 20, 25, 6, 15, 15, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #307
-PAIRING(10, 15, 20, 25, 6, 15, 15, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #308
-PAIRING(10, 15, 20, 25, 6, 15, 15, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #309
-PAIRING(10, 15, 20, 25, 6, 15, 15, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #310
-PAIRING(10, 15, 20, 25, 6, 15, 16, 17, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #311
-PAIRING(10, 15, 20, 25, 6, 15, 16, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #312
-PAIRING(10, 15, 20, 25, 6, 15, 16, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #313
-PAIRING(10, 15, 20, 25, 6, 15, 16, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #314
-PAIRING(10, 15, 20, 25, 6, 15, 16, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #315
-PAIRING(10, 15, 20, 25, 6, 15, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #316
-PAIRING(10, 15, 20, 25, 6, 15, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #317
-PAIRING(10, 15, 20, 25, 6, 15, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #318
-PAIRING(10, 15, 20, 25, 6, 15, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 1) // #319
-PAIRING(10, 15, 20, 25, 6, 15, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #320
-PAIRING(10, 15, 20, 25, 6, 15, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 2) // #321
-PAIRING(10, 15, 20, 25, 6, 15, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #322
-PAIRING(10, 15, 20, 25, 6, 15, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #323
-PAIRING(10, 15, 20, 25, 6, 16, 16, 17, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #324
-PAIRING(10, 15, 20, 25, 6, 16, 16, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #325
-PAIRING(10, 15, 20, 25, 6, 16, 16, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #326
-PAIRING(10, 15, 20, 25, 6, 16, 16, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #327
-PAIRING(10, 15, 20, 25, 6, 16, 16, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #328
-PAIRING(10, 15, 20, 25, 6, 16, 17, 18, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #329
-PAIRING(10, 15, 20, 25, 6, 16, 17, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #330
-PAIRING(10, 15, 20, 25, 6, 16, 17, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #331
-PAIRING(10, 15, 20, 25, 6, 16, 17, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #332
-PAIRING(10, 15, 20, 25, 6, 16, 17, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #333
-PAIRING(10, 15, 20, 25, 6, 16, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #334
-PAIRING(10, 15, 20, 25, 6, 16, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #335
-PAIRING(10, 15, 20, 25, 6, 16, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #336
-PAIRING(10, 15, 20, 25, 6, 16, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 1) // #337
-PAIRING(10, 15, 20, 25, 6, 16, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #338
-PAIRING(10, 15, 20, 25, 6, 16, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 2) // #339
-PAIRING(10, 15, 20, 25, 6, 16, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #340
-PAIRING(10, 15, 20, 25, 6, 16, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #341
-PAIRING(10, 15, 20, 25, 6, 20, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #342
-PAIRING(10, 15, 20, 25, 6, 20, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #343
-PAIRING(10, 15, 20, 25, 6, 20, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #344
-PAIRING(10, 15, 20, 25, 6, 20, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 1) // #345
-PAIRING(10, 15, 20, 25, 6, 20, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #346
-PAIRING(10, 15, 20, 25, 6, 20, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 2) // #347
-PAIRING(10, 15, 20, 25, 6, 20, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #348
-PAIRING(10, 15, 20, 25, 6, 20, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #349
-PAIRING(10, 15, 20, 25, 6, 21, 21, 22, 1, 2, 10, 15, 0, 0, 20, 21, 21, 22, 1, 1) // #350
-PAIRING(10, 15, 20, 25, 6, 21, 21, 25, 1, 2, 10, 15, 0, 0, 20, 21, 21, 25, 0, 1) // #351
-PAIRING(10, 15, 20, 25, 6, 21, 21, 26, 1, 2, 10, 15, 0, 0, 20, 21, 21, 25, 0, 2) // #352
-PAIRING(10, 15, 20, 25, 6, 21, 22, 23, 1, 2, 10, 15, 0, 0, 20, 21, 22, 23, 1, 1) // #353
-PAIRING(10, 15, 20, 25, 6, 21, 22, 25, 1, 2, 10, 15, 0, 0, 20, 21, 22, 25, 1, 1) // #354
-PAIRING(10, 15, 20, 25, 6, 21, 22, 26, 1, 2, 10, 15, 0, 0, 20, 21, 22, 25, 1, 2) // #355
-PAIRING(10, 15, 20, 25, 6, 21, 25, 26, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #356
-PAIRING(10, 15, 20, 25, 6, 21, 26, 27, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #357
-PAIRING(10, 15, 20, 25, 6, 25, 25, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #358
-PAIRING(10, 15, 20, 25, 6, 25, 26, 27, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #359
-PAIRING(10, 15, 20, 25, 6, 26, 26, 27, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #360
-PAIRING(10, 15, 20, 25, 6, 26, 27, 28, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #361
-PAIRING(10, 15, 20, 25, 10, 11, 11, 12, 2, 0, 10, 11, 11, 12, 0, 0, 0, 0, 2, 0) // #362
-PAIRING(10, 15, 20, 25, 10, 11, 11, 15, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 0) // #363
-PAIRING(10, 15, 20, 25, 10, 11, 11, 16, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 1) // #364
-PAIRING(10, 15, 20, 25, 10, 11, 11, 20, 2, 0, 10, 11, 11, 15, 0, 0, 0, 0, 1, 0) // #365
-PAIRING(10, 15, 20, 25, 10, 11, 11, 21, 2, 1, 10, 11, 11, 15, 20, 21, 0, 0, 1, 1) // #366
-PAIRING(10, 15, 20, 25, 10, 11, 11, 25, 2, 1, 10, 11, 11, 15, 20, 25, 0, 0, 0, 1) // #367
-PAIRING(10, 15, 20, 25, 10, 11, 11, 26, 2, 1, 10, 11, 11, 15, 20, 25, 0, 0, 0, 1) // #368
-PAIRING(10, 15, 20, 25, 10, 11, 12, 13, 2, 0, 10, 11, 12, 13, 0, 0, 0, 0, 2, 0) // #369
-PAIRING(10, 15, 20, 25, 10, 11, 12, 15, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 0) // #370
-PAIRING(10, 15, 20, 25, 10, 11, 12, 16, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 1) // #371
-PAIRING(10, 15, 20, 25, 10, 11, 12, 20, 2, 0, 10, 11, 12, 15, 0, 0, 0, 0, 2, 0) // #372
-PAIRING(10, 15, 20, 25, 10, 11, 12, 21, 2, 1, 10, 11, 12, 15, 20, 21, 0, 0, 2, 1) // #373
-PAIRING(10, 15, 20, 25, 10, 11, 12, 25, 2, 1, 10, 11, 12, 15, 20, 25, 0, 0, 1, 1) // #374
-PAIRING(10, 15, 20, 25, 10, 11, 12, 26, 2, 1, 10, 11, 12, 15, 20, 25, 0, 0, 1, 1) // #375
-PAIRING(10, 15, 20, 25, 10, 11, 15, 16, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #376
-PAIRING(10, 15, 20, 25, 10, 11, 15, 20, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #377
-PAIRING(10, 15, 20, 25, 10, 11, 15, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 1) // #378
-PAIRING(10, 15, 20, 25, 10, 11, 15, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #379
-PAIRING(10, 15, 20, 25, 10, 11, 15, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #380
-PAIRING(10, 15, 20, 25, 10, 11, 16, 17, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #381
-PAIRING(10, 15, 20, 25, 10, 11, 16, 20, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #382
-PAIRING(10, 15, 20, 25, 10, 11, 16, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 1) // #383
-PAIRING(10, 15, 20, 25, 10, 11, 16, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #384
-PAIRING(10, 15, 20, 25, 10, 11, 16, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #385
-PAIRING(10, 15, 20, 25, 10, 11, 20, 21, 1, 1, 10, 11, 0, 0, 20, 21, 0, 0, 2, 0) // #386
-PAIRING(10, 15, 20, 25, 10, 11, 20, 25, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 0) // #387
-PAIRING(10, 15, 20, 25, 10, 11, 20, 26, 1, 1, 10, 11, 0, 0, 20, 25, 0, 0, 1, 1) // #388
-PAIRING(10, 15, 20, 25, 10, 11, 21, 22, 1, 1, 10, 11, 0, 0, 21, 22, 0, 0, 2, 0) // #389
-PAIRING(10, 15, 20, 25, 10, 11, 21, 25, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 0) // #390
-PAIRING(10, 15, 20, 25, 10, 11, 21, 26, 1, 1, 10, 11, 0, 0, 21, 25, 0, 0, 2, 1) // #391
-PAIRING(10, 15, 20, 25, 10, 11, 25, 26, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #392
-PAIRING(10, 15, 20, 25, 10, 11, 26, 27, 1, 0, 10, 11, 0, 0, 0, 0, 0, 0, 2, 1) // #393
-PAIRING(10, 15, 20, 25, 10, 15, 15, 16, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #394
-PAIRING(10, 15, 20, 25, 10, 15, 15, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #395
-PAIRING(10, 15, 20, 25, 10, 15, 15, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #396
-PAIRING(10, 15, 20, 25, 10, 15, 15, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #397
-PAIRING(10, 15, 20, 25, 10, 15, 15, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #398
-PAIRING(10, 15, 20, 25, 10, 15, 16, 17, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #399
-PAIRING(10, 15, 20, 25, 10, 15, 16, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #400
-PAIRING(10, 15, 20, 25, 10, 15, 16, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #401
-PAIRING(10, 15, 20, 25, 10, 15, 16, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #402
-PAIRING(10, 15, 20, 25, 10, 15, 16, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #403
-PAIRING(10, 15, 20, 25, 10, 15, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 0) // #404
-PAIRING(10, 15, 20, 25, 10, 15, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 0) // #405
-PAIRING(10, 15, 20, 25, 10, 15, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #406
-PAIRING(10, 15, 20, 25, 10, 15, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 0) // #407
-PAIRING(10, 15, 20, 25, 10, 15, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 0) // #408
-PAIRING(10, 15, 20, 25, 10, 15, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #409
-PAIRING(10, 15, 20, 25, 10, 15, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #410
-PAIRING(10, 15, 20, 25, 10, 15, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #411
-PAIRING(10, 15, 20, 25, 10, 16, 16, 17, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #412
-PAIRING(10, 15, 20, 25, 10, 16, 16, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #413
-PAIRING(10, 15, 20, 25, 10, 16, 16, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #414
-PAIRING(10, 15, 20, 25, 10, 16, 16, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #415
-PAIRING(10, 15, 20, 25, 10, 16, 16, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #416
-PAIRING(10, 15, 20, 25, 10, 16, 17, 18, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #417
-PAIRING(10, 15, 20, 25, 10, 16, 17, 20, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #418
-PAIRING(10, 15, 20, 25, 10, 16, 17, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #419
-PAIRING(10, 15, 20, 25, 10, 16, 17, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #420
-PAIRING(10, 15, 20, 25, 10, 16, 17, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #421
-PAIRING(10, 15, 20, 25, 10, 16, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 1) // #422
-PAIRING(10, 15, 20, 25, 10, 16, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #423
-PAIRING(10, 15, 20, 25, 10, 16, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #424
-PAIRING(10, 15, 20, 25, 10, 16, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 1) // #425
-PAIRING(10, 15, 20, 25, 10, 16, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #426
-PAIRING(10, 15, 20, 25, 10, 16, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 2) // #427
-PAIRING(10, 15, 20, 25, 10, 16, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #428
-PAIRING(10, 15, 20, 25, 10, 16, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 2) // #429
-PAIRING(10, 15, 20, 25, 10, 20, 20, 21, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 0) // #430
-PAIRING(10, 15, 20, 25, 10, 20, 20, 25, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 0) // #431
-PAIRING(10, 15, 20, 25, 10, 20, 20, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 1) // #432
-PAIRING(10, 15, 20, 25, 10, 20, 21, 22, 1, 1, 10, 15, 0, 0, 21, 22, 0, 0, 1, 0) // #433
-PAIRING(10, 15, 20, 25, 10, 20, 21, 25, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 0) // #434
-PAIRING(10, 15, 20, 25, 10, 20, 21, 26, 1, 1, 10, 15, 0, 0, 21, 25, 0, 0, 1, 1) // #435
-PAIRING(10, 15, 20, 25, 10, 20, 25, 26, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #436
-PAIRING(10, 15, 20, 25, 10, 20, 26, 27, 1, 0, 10, 15, 0, 0, 0, 0, 0, 0, 1, 1) // #437
-PAIRING(10, 15, 20, 25, 10, 21, 21, 22, 1, 2, 10, 15, 0, 0, 20, 21, 21, 22, 1, 1) // #438
-PAIRING(10, 15, 20, 25, 10, 21, 21, 25, 1, 2, 10, 15, 0, 0, 20, 21, 21, 25, 0, 1) // #439
-PAIRING(10, 15, 20, 25, 10, 21, 21, 26, 1, 2, 10, 15, 0, 0, 20, 21, 21, 25, 0, 2) // #440
-PAIRING(10, 15, 20, 25, 10, 21, 22, 23, 1, 2, 10, 15, 0, 0, 20, 21, 22, 23, 1, 1) // #441
-PAIRING(10, 15, 20, 25, 10, 21, 22, 25, 1, 2, 10, 15, 0, 0, 20, 21, 22, 25, 1, 1) // #442
-PAIRING(10, 15, 20, 25, 10, 21, 22, 26, 1, 2, 10, 15, 0, 0, 20, 21, 22, 25, 1, 2) // #443
-PAIRING(10, 15, 20, 25, 10, 21, 25, 26, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #444
-PAIRING(10, 15, 20, 25, 10, 21, 26, 27, 1, 1, 10, 15, 0, 0, 20, 21, 0, 0, 1, 2) // #445
-PAIRING(10, 15, 20, 25, 10, 25, 25, 26, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #446
-PAIRING(10, 15, 20, 25, 10, 25, 26, 27, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #447
-PAIRING(10, 15, 20, 25, 10, 26, 26, 27, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #448
-PAIRING(10, 15, 20, 25, 10, 26, 27, 28, 1, 1, 10, 15, 0, 0, 20, 25, 0, 0, 0, 2) // #449
-PAIRING(10, 15, 20, 25, 11, 12, 12, 13, 2, 0, 11, 12, 12, 13, 0, 0, 0, 0, 2, 0) // #450
-PAIRING(10, 15, 20, 25, 11, 12, 12, 15, 2, 0, 11, 12, 12, 15, 0, 0, 0, 0, 2, 0) // #451
-PAIRING(10, 15, 20, 25, 11, 12, 12, 16, 2, 0, 11, 12, 12, 15, 0, 0, 0, 0, 2, 1) // #452
-PAIRING(10, 15, 20, 25, 11, 12, 12, 20, 2, 0, 11, 12, 12, 15, 0, 0, 0, 0, 2, 0) // #453
-PAIRING(10, 15, 20, 25, 11, 12, 12, 21, 2, 1, 11, 12, 12, 15, 20, 21, 0, 0, 2, 1) // #454
-PAIRING(10, 15, 20, 25, 11, 12, 12, 25, 2, 1, 11, 12, 12, 15, 20, 25, 0, 0, 1, 1) // #455
-PAIRING(10, 15, 20, 25, 11, 12, 12, 26, 2, 1, 11, 12, 12, 15, 20, 25, 0, 0, 1, 1) // #456
-PAIRING(10, 15, 20, 25, 11, 12, 13, 14, 2, 0, 11, 12, 13, 14, 0, 0, 0, 0, 2, 0) // #457
-PAIRING(10, 15, 20, 25, 11, 12, 13, 15, 2, 0, 11, 12, 13, 15, 0, 0, 0, 0, 2, 0) // #458
-PAIRING(10, 15, 20, 25, 11, 12, 13, 16, 2, 0, 11, 12, 13, 15, 0, 0, 0, 0, 2, 1) // #459
-PAIRING(10, 15, 20, 25, 11, 12, 13, 20, 2, 0, 11, 12, 13, 15, 0, 0, 0, 0, 2, 0) // #460
-PAIRING(10, 15, 20, 25, 11, 12, 13, 21, 2, 1, 11, 12, 13, 15, 20, 21, 0, 0, 2, 1) // #461
-PAIRING(10, 15, 20, 25, 11, 12, 13, 25, 2, 1, 11, 12, 13, 15, 20, 25, 0, 0, 1, 1) // #462
-PAIRING(10, 15, 20, 25, 11, 12, 13, 26, 2, 1, 11, 12, 13, 15, 20, 25, 0, 0, 1, 1) // #463
-PAIRING(10, 15, 20, 25, 11, 12, 15, 16, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #464
-PAIRING(10, 15, 20, 25, 11, 12, 15, 20, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #465
-PAIRING(10, 15, 20, 25, 11, 12, 15, 21, 1, 1, 11, 12, 0, 0, 20, 21, 0, 0, 2, 1) // #466
-PAIRING(10, 15, 20, 25, 11, 12, 15, 25, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #467
-PAIRING(10, 15, 20, 25, 11, 12, 15, 26, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #468
-PAIRING(10, 15, 20, 25, 11, 12, 16, 17, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #469
-PAIRING(10, 15, 20, 25, 11, 12, 16, 20, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #470
-PAIRING(10, 15, 20, 25, 11, 12, 16, 21, 1, 1, 11, 12, 0, 0, 20, 21, 0, 0, 2, 1) // #471
-PAIRING(10, 15, 20, 25, 11, 12, 16, 25, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #472
-PAIRING(10, 15, 20, 25, 11, 12, 16, 26, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #473
-PAIRING(10, 15, 20, 25, 11, 12, 20, 21, 1, 1, 11, 12, 0, 0, 20, 21, 0, 0, 2, 0) // #474
-PAIRING(10, 15, 20, 25, 11, 12, 20, 25, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 0) // #475
-PAIRING(10, 15, 20, 25, 11, 12, 20, 26, 1, 1, 11, 12, 0, 0, 20, 25, 0, 0, 1, 1) // #476
-PAIRING(10, 15, 20, 25, 11, 12, 21, 22, 1, 1, 11, 12, 0, 0, 21, 22, 0, 0, 2, 0) // #477
-PAIRING(10, 15, 20, 25, 11, 12, 21, 25, 1, 1, 11, 12, 0, 0, 21, 25, 0, 0, 2, 0) // #478
-PAIRING(10, 15, 20, 25, 11, 12, 21, 26, 1, 1, 11, 12, 0, 0, 21, 25, 0, 0, 2, 1) // #479
-PAIRING(10, 15, 20, 25, 11, 12, 25, 26, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #480
-PAIRING(10, 15, 20, 25, 11, 12, 26, 27, 1, 0, 11, 12, 0, 0, 0, 0, 0, 0, 2, 1) // #481
-PAIRING(10, 15, 20, 25, 11, 15, 15, 16, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #482
-PAIRING(10, 15, 20, 25, 11, 15, 15, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #483
-PAIRING(10, 15, 20, 25, 11, 15, 15, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 1) // #484
-PAIRING(10, 15, 20, 25, 11, 15, 15, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #485
-PAIRING(10, 15, 20, 25, 11, 15, 15, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #486
-PAIRING(10, 15, 20, 25, 11, 15, 16, 17, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #487
-PAIRING(10, 15, 20, 25, 11, 15, 16, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #488
-PAIRING(10, 15, 20, 25, 11, 15, 16, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 1) // #489
-PAIRING(10, 15, 20, 25, 11, 15, 16, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #490
-PAIRING(10, 15, 20, 25, 11, 15, 16, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #491
-PAIRING(10, 15, 20, 25, 11, 15, 20, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 0) // #492
-PAIRING(10, 15, 20, 25, 11, 15, 20, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 0) // #493
-PAIRING(10, 15, 20, 25, 11, 15, 20, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #494
-PAIRING(10, 15, 20, 25, 11, 15, 21, 22, 1, 1, 11, 15, 0, 0, 21, 22, 0, 0, 2, 0) // #495
-PAIRING(10, 15, 20, 25, 11, 15, 21, 25, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 0) // #496
-PAIRING(10, 15, 20, 25, 11, 15, 21, 26, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 1) // #497
-PAIRING(10, 15, 20, 25, 11, 15, 25, 26, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #498
-PAIRING(10, 15, 20, 25, 11, 15, 26, 27, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #499
-PAIRING(10, 15, 20, 25, 11, 16, 16, 17, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #500
-PAIRING(10, 15, 20, 25, 11, 16, 16, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #501
-PAIRING(10, 15, 20, 25, 11, 16, 16, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #502
-PAIRING(10, 15, 20, 25, 11, 16, 16, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #503
-PAIRING(10, 15, 20, 25, 11, 16, 16, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #504
-PAIRING(10, 15, 20, 25, 11, 16, 17, 18, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #505
-PAIRING(10, 15, 20, 25, 11, 16, 17, 20, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #506
-PAIRING(10, 15, 20, 25, 11, 16, 17, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #507
-PAIRING(10, 15, 20, 25, 11, 16, 17, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #508
-PAIRING(10, 15, 20, 25, 11, 16, 17, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #509
-PAIRING(10, 15, 20, 25, 11, 16, 20, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 1) // #510
-PAIRING(10, 15, 20, 25, 11, 16, 20, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #511
-PAIRING(10, 15, 20, 25, 11, 16, 20, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #512
-PAIRING(10, 15, 20, 25, 11, 16, 21, 22, 1, 1, 11, 15, 0, 0, 21, 22, 0, 0, 2, 1) // #513
-PAIRING(10, 15, 20, 25, 11, 16, 21, 25, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 1) // #514
-PAIRING(10, 15, 20, 25, 11, 16, 21, 26, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 2) // #515
-PAIRING(10, 15, 20, 25, 11, 16, 25, 26, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #516
-PAIRING(10, 15, 20, 25, 11, 16, 26, 27, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 2) // #517
-PAIRING(10, 15, 20, 25, 11, 20, 20, 21, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 0) // #518
-PAIRING(10, 15, 20, 25, 11, 20, 20, 25, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 0) // #519
-PAIRING(10, 15, 20, 25, 11, 20, 20, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 1) // #520
-PAIRING(10, 15, 20, 25, 11, 20, 21, 22, 1, 1, 11, 15, 0, 0, 21, 22, 0, 0, 2, 0) // #521
-PAIRING(10, 15, 20, 25, 11, 20, 21, 25, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 0) // #522
-PAIRING(10, 15, 20, 25, 11, 20, 21, 26, 1, 1, 11, 15, 0, 0, 21, 25, 0, 0, 2, 1) // #523
-PAIRING(10, 15, 20, 25, 11, 20, 25, 26, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #524
-PAIRING(10, 15, 20, 25, 11, 20, 26, 27, 1, 0, 11, 15, 0, 0, 0, 0, 0, 0, 2, 1) // #525
-PAIRING(10, 15, 20, 25, 11, 21, 21, 22, 1, 2, 11, 15, 0, 0, 20, 21, 21, 22, 2, 1) // #526
-PAIRING(10, 15, 20, 25, 11, 21, 21, 25, 1, 2, 11, 15, 0, 0, 20, 21, 21, 25, 1, 1) // #527
-PAIRING(10, 15, 20, 25, 11, 21, 21, 26, 1, 2, 11, 15, 0, 0, 20, 21, 21, 25, 1, 2) // #528
-PAIRING(10, 15, 20, 25, 11, 21, 22, 23, 1, 2, 11, 15, 0, 0, 20, 21, 22, 23, 2, 1) // #529
-PAIRING(10, 15, 20, 25, 11, 21, 22, 25, 1, 2, 11, 15, 0, 0, 20, 21, 22, 25, 2, 1) // #530
-PAIRING(10, 15, 20, 25, 11, 21, 22, 26, 1, 2, 11, 15, 0, 0, 20, 21, 22, 25, 2, 2) // #531
-PAIRING(10, 15, 20, 25, 11, 21, 25, 26, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #532
-PAIRING(10, 15, 20, 25, 11, 21, 26, 27, 1, 1, 11, 15, 0, 0, 20, 21, 0, 0, 2, 2) // #533
-PAIRING(10, 15, 20, 25, 11, 25, 25, 26, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #534
-PAIRING(10, 15, 20, 25, 11, 25, 26, 27, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #535
-PAIRING(10, 15, 20, 25, 11, 26, 26, 27, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #536
-PAIRING(10, 15, 20, 25, 11, 26, 27, 28, 1, 1, 11, 15, 0, 0, 20, 25, 0, 0, 1, 2) // #537
-PAIRING(10, 15, 20, 25, 15, 16, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #538
-PAIRING(10, 15, 20, 25, 15, 16, 16, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #539
-PAIRING(10, 15, 20, 25, 15, 16, 16, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #540
-PAIRING(10, 15, 20, 25, 15, 16, 16, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #541
-PAIRING(10, 15, 20, 25, 15, 16, 16, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #542
-PAIRING(10, 15, 20, 25, 15, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #543
-PAIRING(10, 15, 20, 25, 15, 16, 17, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #544
-PAIRING(10, 15, 20, 25, 15, 16, 17, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #545
-PAIRING(10, 15, 20, 25, 15, 16, 17, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #546
-PAIRING(10, 15, 20, 25, 15, 16, 17, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #547
-PAIRING(10, 15, 20, 25, 15, 16, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #548
-PAIRING(10, 15, 20, 25, 15, 16, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #549
-PAIRING(10, 15, 20, 25, 15, 16, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #550
-PAIRING(10, 15, 20, 25, 15, 16, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #551
-PAIRING(10, 15, 20, 25, 15, 16, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #552
-PAIRING(10, 15, 20, 25, 15, 16, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #553
-PAIRING(10, 15, 20, 25, 15, 16, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #554
-PAIRING(10, 15, 20, 25, 15, 16, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #555
-PAIRING(10, 15, 20, 25, 15, 20, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #556
-PAIRING(10, 15, 20, 25, 15, 20, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #557
-PAIRING(10, 15, 20, 25, 15, 20, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #558
-PAIRING(10, 15, 20, 25, 15, 20, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #559
-PAIRING(10, 15, 20, 25, 15, 20, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #560
-PAIRING(10, 15, 20, 25, 15, 20, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #561
-PAIRING(10, 15, 20, 25, 15, 20, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #562
-PAIRING(10, 15, 20, 25, 15, 20, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #563
-PAIRING(10, 15, 20, 25, 15, 21, 21, 22, 0, 2, 0, 0, 0, 0, 20, 21, 21, 22, 2, 1) // #564
-PAIRING(10, 15, 20, 25, 15, 21, 21, 25, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 1) // #565
-PAIRING(10, 15, 20, 25, 15, 21, 21, 26, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 2) // #566
-PAIRING(10, 15, 20, 25, 15, 21, 22, 23, 0, 2, 0, 0, 0, 0, 20, 21, 22, 23, 2, 1) // #567
-PAIRING(10, 15, 20, 25, 15, 21, 22, 25, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 1) // #568
-PAIRING(10, 15, 20, 25, 15, 21, 22, 26, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 2) // #569
-PAIRING(10, 15, 20, 25, 15, 21, 25, 26, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #570
-PAIRING(10, 15, 20, 25, 15, 21, 26, 27, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #571
-PAIRING(10, 15, 20, 25, 15, 25, 25, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #572
-PAIRING(10, 15, 20, 25, 15, 25, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #573
-PAIRING(10, 15, 20, 25, 15, 26, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #574
-PAIRING(10, 15, 20, 25, 15, 26, 27, 28, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #575
-PAIRING(10, 15, 20, 25, 16, 17, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #576
-PAIRING(10, 15, 20, 25, 16, 17, 17, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #577
-PAIRING(10, 15, 20, 25, 16, 17, 17, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #578
-PAIRING(10, 15, 20, 25, 16, 17, 17, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #579
-PAIRING(10, 15, 20, 25, 16, 17, 17, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #580
-PAIRING(10, 15, 20, 25, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #581
-PAIRING(10, 15, 20, 25, 16, 17, 18, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #582
-PAIRING(10, 15, 20, 25, 16, 17, 18, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #583
-PAIRING(10, 15, 20, 25, 16, 17, 18, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #584
-PAIRING(10, 15, 20, 25, 16, 17, 18, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #585
-PAIRING(10, 15, 20, 25, 16, 17, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #586
-PAIRING(10, 15, 20, 25, 16, 17, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #587
-PAIRING(10, 15, 20, 25, 16, 17, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #588
-PAIRING(10, 15, 20, 25, 16, 17, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #589
-PAIRING(10, 15, 20, 25, 16, 17, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #590
-PAIRING(10, 15, 20, 25, 16, 17, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #591
-PAIRING(10, 15, 20, 25, 16, 17, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #592
-PAIRING(10, 15, 20, 25, 16, 17, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #593
-PAIRING(10, 15, 20, 25, 16, 20, 20, 21, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #594
-PAIRING(10, 15, 20, 25, 16, 20, 20, 25, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #595
-PAIRING(10, 15, 20, 25, 16, 20, 20, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #596
-PAIRING(10, 15, 20, 25, 16, 20, 21, 22, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #597
-PAIRING(10, 15, 20, 25, 16, 20, 21, 25, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #598
-PAIRING(10, 15, 20, 25, 16, 20, 21, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #599
-PAIRING(10, 15, 20, 25, 16, 20, 25, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #600
-PAIRING(10, 15, 20, 25, 16, 20, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #601
-PAIRING(10, 15, 20, 25, 16, 21, 21, 22, 0, 2, 0, 0, 0, 0, 20, 21, 21, 22, 2, 1) // #602
-PAIRING(10, 15, 20, 25, 16, 21, 21, 25, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 1) // #603
-PAIRING(10, 15, 20, 25, 16, 21, 21, 26, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 2) // #604
-PAIRING(10, 15, 20, 25, 16, 21, 22, 23, 0, 2, 0, 0, 0, 0, 20, 21, 22, 23, 2, 1) // #605
-PAIRING(10, 15, 20, 25, 16, 21, 22, 25, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 1) // #606
-PAIRING(10, 15, 20, 25, 16, 21, 22, 26, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 2) // #607
-PAIRING(10, 15, 20, 25, 16, 21, 25, 26, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #608
-PAIRING(10, 15, 20, 25, 16, 21, 26, 27, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 2) // #609
-PAIRING(10, 15, 20, 25, 16, 25, 25, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #610
-PAIRING(10, 15, 20, 25, 16, 25, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #611
-PAIRING(10, 15, 20, 25, 16, 26, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #612
-PAIRING(10, 15, 20, 25, 16, 26, 27, 28, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #613
-PAIRING(10, 15, 20, 25, 20, 21, 21, 22, 0, 2, 0, 0, 0, 0, 20, 21, 21, 22, 2, 0) // #614
-PAIRING(10, 15, 20, 25, 20, 21, 21, 25, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 0) // #615
-PAIRING(10, 15, 20, 25, 20, 21, 21, 26, 0, 2, 0, 0, 0, 0, 20, 21, 21, 25, 1, 1) // #616
-PAIRING(10, 15, 20, 25, 20, 21, 22, 23, 0, 2, 0, 0, 0, 0, 20, 21, 22, 23, 2, 0) // #617
-PAIRING(10, 15, 20, 25, 20, 21, 22, 25, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 0) // #618
-PAIRING(10, 15, 20, 25, 20, 21, 22, 26, 0, 2, 0, 0, 0, 0, 20, 21, 22, 25, 2, 1) // #619
-PAIRING(10, 15, 20, 25, 20, 21, 25, 26, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #620
-PAIRING(10, 15, 20, 25, 20, 21, 26, 27, 0, 1, 0, 0, 0, 0, 20, 21, 0, 0, 2, 1) // #621
-PAIRING(10, 15, 20, 25, 20, 25, 25, 26, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #622
-PAIRING(10, 15, 20, 25, 20, 25, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 1) // #623
-PAIRING(10, 15, 20, 25, 20, 26, 26, 27, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #624
-PAIRING(10, 15, 20, 25, 20, 26, 27, 28, 0, 1, 0, 0, 0, 0, 20, 25, 0, 0, 1, 2) // #625
-PAIRING(10, 15, 20, 25, 21, 22, 22, 23, 0, 2, 0, 0, 0, 0, 21, 22, 22, 23, 2, 0) // #626
-PAIRING(10, 15, 20, 25, 21, 22, 22, 25, 0, 2, 0, 0, 0, 0, 21, 22, 22, 25, 2, 0) // #627
-PAIRING(10, 15, 20, 25, 21, 22, 22, 26, 0, 2, 0, 0, 0, 0, 21, 22, 22, 25, 2, 1) // #628
-PAIRING(10, 15, 20, 25, 21, 22, 23, 24, 0, 2, 0, 0, 0, 0, 21, 22, 23, 24, 2, 0) // #629
-PAIRING(10, 15, 20, 25, 21, 22, 23, 25, 0, 2, 0, 0, 0, 0, 21, 22, 23, 25, 2, 0) // #630
-PAIRING(10, 15, 20, 25, 21, 22, 23, 26, 0, 2, 0, 0, 0, 0, 21, 22, 23, 25, 2, 1) // #631
-PAIRING(10, 15, 20, 25, 21, 22, 25, 26, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #632
-PAIRING(10, 15, 20, 25, 21, 22, 26, 27, 0, 1, 0, 0, 0, 0, 21, 22, 0, 0, 2, 1) // #633
-PAIRING(10, 15, 20, 25, 21, 25, 25, 26, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #634
-PAIRING(10, 15, 20, 25, 21, 25, 26, 27, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 1) // #635
-PAIRING(10, 15, 20, 25, 21, 26, 26, 27, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #636
-PAIRING(10, 15, 20, 25, 21, 26, 27, 28, 0, 1, 0, 0, 0, 0, 21, 25, 0, 0, 2, 2) // #637
-PAIRING(10, 15, 20, 25, 25, 26, 26, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #638
-PAIRING(10, 15, 20, 25, 25, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #639
-PAIRING(10, 15, 20, 25, 26, 27, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #640
-PAIRING(10, 15, 20, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2) // #641
diff --git a/toolkit/crashreporter/google-breakpad/src/common/tests/auto_tempdir.h b/toolkit/crashreporter/google-breakpad/src/common/tests/auto_tempdir.h
deleted file mode 100644
index 1df88db8b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/tests/auto_tempdir.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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.
-
-// Utility class for creating a temporary directory for unit tests
-// that is deleted in the destructor.
-#ifndef GOOGLE_BREAKPAD_COMMON_TESTS_AUTO_TEMPDIR
-#define GOOGLE_BREAKPAD_COMMON_TESTS_AUTO_TEMPDIR
-
-#include <dirent.h>
-#include <sys/types.h>
-
-#include <string>
-
-#include "breakpad_googletest_includes.h"
-#include "common/using_std_string.h"
-
-#if !defined(__ANDROID__)
-#define TEMPDIR "/tmp"
-#else
-#define TEMPDIR "/data/local/tmp"
-#include "common/android/testing/mkdtemp.h"
-#endif
-
-namespace google_breakpad {
-
-class AutoTempDir {
- public:
- AutoTempDir() {
- char temp_dir[] = TEMPDIR "/breakpad.XXXXXX";
- EXPECT_TRUE(mkdtemp(temp_dir) != NULL);
- path_.assign(temp_dir);
- }
-
- ~AutoTempDir() {
- DeleteRecursively(path_);
- }
-
- const string& path() const {
- return path_;
- }
-
- private:
- void DeleteRecursively(const string& path) {
- // First remove any files in the dir
- DIR* dir = opendir(path.c_str());
- if (!dir)
- return;
-
- dirent* entry;
- while ((entry = readdir(dir)) != NULL) {
- if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
- continue;
- string entry_path = path + "/" + entry->d_name;
- struct stat stats;
- EXPECT_TRUE(lstat(entry_path.c_str(), &stats) == 0);
- if (S_ISDIR(stats.st_mode))
- DeleteRecursively(entry_path);
- else
- EXPECT_TRUE(unlink(entry_path.c_str()) == 0);
- }
- EXPECT_TRUE(closedir(dir) == 0);
- EXPECT_TRUE(rmdir(path.c_str()) == 0);
- }
-
- // prevent copy construction and assignment
- AutoTempDir(const AutoTempDir&);
- AutoTempDir& operator=(const AutoTempDir&);
-
- string path_;
-};
-
-} // namespace google_breakpad
-
-#endif // GOOGLE_BREAKPAD_COMMON_TESTS_AUTO_TEMPDIR
diff --git a/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.cc b/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.cc
deleted file mode 100644
index 1c041777c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-// 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.
-
-// file_utils.cc: Implement utility functions for file manipulation.
-// See file_utils.h for details.
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "common/linux/eintr_wrapper.h"
-#include "common/tests/file_utils.h"
-
-namespace google_breakpad {
-
-bool CopyFile(const char* from_path, const char* to_path) {
- int infile = HANDLE_EINTR(open(from_path, O_RDONLY));
- if (infile < 0) {
- perror("open");
- return false;
- }
-
- int outfile = HANDLE_EINTR(creat(to_path, 0666));
- if (outfile < 0) {
- perror("creat");
- if (IGNORE_EINTR(close(infile)) < 0) {
- perror("close");
- }
- return false;
- }
-
- char buffer[1024];
- bool result = true;
-
- while (result) {
- ssize_t bytes_read = HANDLE_EINTR(read(infile, buffer, sizeof(buffer)));
- if (bytes_read < 0) {
- perror("read");
- result = false;
- break;
- }
- if (bytes_read == 0)
- break;
- ssize_t bytes_written_per_read = 0;
- do {
- ssize_t bytes_written_partial = HANDLE_EINTR(write(
- outfile,
- &buffer[bytes_written_per_read],
- bytes_read - bytes_written_per_read));
- if (bytes_written_partial < 0) {
- perror("write");
- result = false;
- break;
- }
- bytes_written_per_read += bytes_written_partial;
- } while (bytes_written_per_read < bytes_read);
- }
-
- if (IGNORE_EINTR(close(infile)) == -1) {
- perror("close");
- result = false;
- }
- if (IGNORE_EINTR(close(outfile)) == -1) {
- perror("close");
- result = false;
- }
-
- return result;
-}
-
-bool ReadFile(const char* path, void* buffer, ssize_t* buffer_size) {
- int fd = HANDLE_EINTR(open(path, O_RDONLY));
- if (fd == -1) {
- perror("open");
- return false;
- }
-
- bool ok = true;
- if (buffer && buffer_size && *buffer_size > 0) {
- memset(buffer, 0, sizeof(*buffer_size));
- *buffer_size = HANDLE_EINTR(read(fd, buffer, *buffer_size));
- if (*buffer_size == -1) {
- perror("read");
- ok = false;
- }
- }
- if (IGNORE_EINTR(close(fd)) == -1) {
- perror("close");
- ok = false;
- }
- return ok;
-}
-
-bool WriteFile(const char* path, const void* buffer, size_t buffer_size) {
- int fd = HANDLE_EINTR(open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU));
- if (fd == -1) {
- perror("open");
- return false;
- }
-
- bool ok = true;
- if (buffer) {
- size_t bytes_written_total = 0;
- ssize_t bytes_written_partial = 0;
- const char* data = reinterpret_cast<const char*>(buffer);
- while (bytes_written_total < buffer_size) {
- bytes_written_partial =
- HANDLE_EINTR(write(fd, data + bytes_written_total,
- buffer_size - bytes_written_total));
- if (bytes_written_partial < 0) {
- perror("write");
- ok = false;
- break;
- }
- bytes_written_total += bytes_written_partial;
- }
- }
- if (IGNORE_EINTR(close(fd)) == -1) {
- perror("close");
- ok = false;
- }
- return ok;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.h b/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.h
deleted file mode 100644
index c98a9bfa8..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/tests/file_utils.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-// file_utils.h: Define utility functions for file manipulation, which
-// are used for testing.
-
-#ifndef COMMON_TESTS_FILE_UTILS_H_
-#define COMMON_TESTS_FILE_UTILS_H_
-
-namespace google_breakpad {
-
-// Copies a file from |from_path| to |to_path|. Returns true on success.
-bool CopyFile(const char* from_path, const char* to_path);
-
-// Reads the content of a file at |path| into |buffer|. |buffer_size| specifies
-// the size of |buffer| in bytes and returns the number of bytes read from the
-// file on success. Returns true on success.
-bool ReadFile(const char* path, void* buffer, ssize_t* buffer_size);
-
-// Writes |buffer_size| bytes of the content in |buffer| to a file at |path|.
-// Returns true on success.
-bool WriteFile(const char* path, const void* buffer, size_t buffer_size);
-
-} // namespace google_breakpad
-
-#endif // COMMON_TESTS_FILE_UTILS_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/unordered.h b/toolkit/crashreporter/google-breakpad/src/common/unordered.h
deleted file mode 100644
index ec665cc02..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/unordered.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// 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 this file to use unordered_map and unordered_set. If tr1
-// or C++11 is not available, you can switch to using hash_set and
-// hash_map by defining BP_USE_HASH_SET.
-
-#ifndef COMMON_UNORDERED_H_
-#define COMMON_UNORDERED_H_
-
-#if defined(BP_USE_HASH_SET)
-#include <hash_map>
-#include <hash_set>
-
-// For hash<string>.
-#include "util/hash/hash.h"
-
-template <class T, class U, class H = __gnu_cxx::hash<T> >
-struct unordered_map : public hash_map<T, U, H> {};
-template <class T, class H = __gnu_cxx::hash<T> >
-struct unordered_set : public hash_set<T, H> {};
-
-#elif defined(_LIBCPP_VERSION) // c++11
-#include <unordered_map>
-#include <unordered_set>
-using std::unordered_map;
-using std::unordered_set;
-
-#else // Fallback to tr1::unordered
-#include <tr1/unordered_map>
-#include <tr1/unordered_set>
-using std::tr1::unordered_map;
-using std::tr1::unordered_set;
-#endif
-
-#endif // COMMON_UNORDERED_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/using_std_string.h b/toolkit/crashreporter/google-breakpad/src/common/using_std_string.h
deleted file mode 100644
index 13c1da59c..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/using_std_string.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// -*- mode: C++ -*-
-
-// Copyright (c) 2012, 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.
-
-// Original author: Ivan Penkov
-
-// using_std_string.h: Allows building this code in environments where
-// global string (::string) exists.
-//
-// The problem:
-// -------------
-// Let's say you want to build this code in an environment where a global
-// string type is defined (i.e. ::string). Now, let's suppose that ::string
-// is different that std::string and you'd like to have the option to easily
-// choose between the two string types. Ideally you'd like to control which
-// string type is chosen by simply #defining an identifier.
-//
-// The solution:
-// -------------
-// #define HAS_GLOBAL_STRING somewhere in a global header file and then
-// globally replace std::string with string. Then include this header
-// file everywhere where string is used. If you want to revert back to
-// using std::string, simply remove the #define (HAS_GLOBAL_STRING).
-
-#ifndef THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
-#define THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
-
-#ifdef HAS_GLOBAL_STRING
- typedef ::string google_breakpad_string;
-#else
- using std::string;
- typedef std::string google_breakpad_string;
-#endif
-
-// Inicates that type google_breakpad_string is defined
-#define HAS_GOOGLE_BREAKPAD_STRING
-
-#endif // THIRD_PARTY_BREAKPAD_SRC_COMMON_USING_STD_STRING_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp b/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp
deleted file mode 100644
index c98333a34..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/common_windows.gyp
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2013 Google Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-{
- 'includes': [
- '../../build/common.gypi',
- ],
- 'targets': [
- {
- 'target_name': 'dia_sdk',
- 'type': 'none',
- 'all_dependent_settings': {
- 'include_dirs': [
- '<(DEPTH)',
- '$(VSInstallDir)/DIA SDK/include',
- ],
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalDependencies': [
- 'diaguids.lib',
- 'imagehlp.lib',
- ],
- },
- },
- 'configurations': {
- 'x86_Base': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalLibraryDirectories':
- ['$(VSInstallDir)/DIA SDK/lib'],
- },
- },
- },
- 'x64_Base': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'AdditionalLibraryDirectories':
- ['$(VSInstallDir)/DIA SDK/lib/amd64'],
- },
- },
- },
- },
- },
- },
- {
- 'target_name': 'common_windows_lib',
- 'type': 'static_library',
- 'sources': [
- 'dia_util.cc',
- 'dia_util.h',
- 'guid_string.cc',
- 'guid_string.h',
- 'http_upload.cc',
- 'http_upload.h',
- 'omap.cc',
- 'omap.h',
- 'omap_internal.h',
- 'pdb_source_line_writer.cc',
- 'pdb_source_line_writer.h',
- 'string_utils.cc',
- 'string_utils-inl.h',
- ],
- 'dependencies': [
- 'dia_sdk',
- ],
- },
- {
- 'target_name': 'common_windows_unittests',
- 'type': 'executable',
- 'sources': [
- 'omap_unittest.cc',
- ],
- 'dependencies': [
- '<(DEPTH)/client/windows/unittests/testing.gyp:gmock',
- '<(DEPTH)/client/windows/unittests/testing.gyp:gtest',
- 'common_windows_lib',
- ],
- },
- ],
-}
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc
deleted file mode 100644
index ed8cb5b65..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/windows/dia_util.h"
-
-#include <atlbase.h>
-
-namespace google_breakpad {
-
-bool FindDebugStream(const wchar_t* name,
- IDiaSession* session,
- IDiaEnumDebugStreamData** debug_stream) {
- CComPtr<IDiaEnumDebugStreams> enum_debug_streams;
- if (FAILED(session->getEnumDebugStreams(&enum_debug_streams))) {
- fprintf(stderr, "IDiaSession::getEnumDebugStreams failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumDebugStreamData> temp_debug_stream;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_debug_streams->Next(1, &temp_debug_stream, &fetched)) &&
- fetched == 1) {
- CComBSTR stream_name;
- if (FAILED(temp_debug_stream->get_name(&stream_name))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::get_name failed\n");
- return false;
- }
-
- // Found the stream?
- if (wcsncmp((LPWSTR)stream_name, name, stream_name.Length()) == 0) {
- *debug_stream = temp_debug_stream.Detach();
- return true;
- }
-
- temp_debug_stream.Release();
- }
-
- // No table was found.
- return false;
-}
-
-bool FindTable(REFIID iid, IDiaSession* session, void** table) {
- // Get the table enumerator.
- CComPtr<IDiaEnumTables> enum_tables;
- if (FAILED(session->getEnumTables(&enum_tables))) {
- fprintf(stderr, "IDiaSession::getEnumTables failed\n");
- return false;
- }
-
- // Iterate through the tables.
- CComPtr<IDiaTable> temp_table;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_tables->Next(1, &temp_table, &fetched)) &&
- fetched == 1) {
- void* temp = NULL;
- if (SUCCEEDED(temp_table->QueryInterface(iid, &temp))) {
- *table = temp;
- return true;
- }
- temp_table.Release();
- }
-
- // The table was not found.
- return false;
-}
-
-} // namespace google_breakpad \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h b/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h
deleted file mode 100644
index b9e0df2d5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/dia_util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Utilities for loading debug streams and tables from a PDB file.
-
-#ifndef COMMON_WINDOWS_DIA_UTIL_H_
-#define COMMON_WINDOWS_DIA_UTIL_H_
-
-#include <Windows.h>
-#include <dia2.h>
-
-namespace google_breakpad {
-
-// Find the debug stream of the given |name| in the given |session|. Returns
-// true on success, false on error of if the stream does not exist. On success
-// the stream will be returned via |debug_stream|.
-bool FindDebugStream(const wchar_t* name,
- IDiaSession* session,
- IDiaEnumDebugStreamData** debug_stream);
-
-// Finds the first table implementing the COM interface with ID |iid| in the
-// given |session|. Returns true on success, false on error or if no such
-// table is found. On success the table will be returned via |table|.
-bool FindTable(REFIID iid, IDiaSession* session, void** table);
-
-// A templated version of FindTable. Finds the first table implementing type
-// |InterfaceType| in the given |session|. Returns true on success, false on
-// error or if no such table is found. On success the table will be returned via
-// |table|.
-template<typename InterfaceType>
-bool FindTable(IDiaSession* session, InterfaceType** table) {
- return FindTable(__uuidof(InterfaceType),
- session,
- reinterpret_cast<void**>(table));
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_DIA_UTIL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
deleted file mode 100644
index b7f877e66..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// guid_string.cc: Convert GUIDs to strings.
-//
-// See guid_string.h for documentation.
-
-#include <wchar.h>
-
-#include "common/windows/string_utils-inl.h"
-
-#include "common/windows/guid_string.h"
-
-namespace google_breakpad {
-
-// static
-wstring GUIDString::GUIDToWString(GUID *guid) {
- wchar_t guid_string[37];
- swprintf(
- guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
- L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- guid->Data1, guid->Data2, guid->Data3,
- guid->Data4[0], guid->Data4[1], guid->Data4[2],
- guid->Data4[3], guid->Data4[4], guid->Data4[5],
- guid->Data4[6], guid->Data4[7]);
-
- // remove when VC++7.1 is no longer supported
- guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0';
-
- return wstring(guid_string);
-}
-
-// static
-wstring GUIDString::GUIDToSymbolServerWString(GUID *guid) {
- wchar_t guid_string[33];
- swprintf(
- guid_string, sizeof(guid_string) / sizeof(guid_string[0]),
- L"%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
- guid->Data1, guid->Data2, guid->Data3,
- guid->Data4[0], guid->Data4[1], guid->Data4[2],
- guid->Data4[3], guid->Data4[4], guid->Data4[5],
- guid->Data4[6], guid->Data4[7]);
-
- // remove when VC++7.1 is no longer supported
- guid_string[sizeof(guid_string) / sizeof(guid_string[0]) - 1] = L'\0';
-
- return wstring(guid_string);
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h b/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
deleted file mode 100644
index 48a5c1d37..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/guid_string.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// guid_string.cc: Convert GUIDs to strings.
-
-#ifndef COMMON_WINDOWS_GUID_STRING_H_
-#define COMMON_WINDOWS_GUID_STRING_H_
-
-#include <guiddef.h>
-
-#include <string>
-
-namespace google_breakpad {
-
-using std::wstring;
-
-class GUIDString {
- public:
- // Converts guid to a string in the format recommended by RFC 4122 and
- // returns the string.
- static wstring GUIDToWString(GUID *guid);
-
- // Converts guid to a string formatted as uppercase hexadecimal, with
- // no separators, and returns the string. This is the format used for
- // symbol server identifiers, although identifiers have an age tacked
- // on to the string.
- static wstring GUIDToSymbolServerWString(GUID *guid);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_GUID_STRING_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
deleted file mode 100644
index 7676bdc5a..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.cc
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <assert.h>
-
-// Disable exception handler warnings.
-#pragma warning(disable:4530)
-
-#include <fstream>
-
-#include "common/windows/string_utils-inl.h"
-
-#include "common/windows/http_upload.h"
-
-namespace google_breakpad {
-
-using std::ifstream;
-using std::ios;
-
-static const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";
-
-// Helper class which closes an internet handle when it goes away
-class HTTPUpload::AutoInternetHandle {
- public:
- explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
- ~AutoInternetHandle() {
- if (handle_) {
- InternetCloseHandle(handle_);
- }
- }
-
- HINTERNET get() { return handle_; }
-
- private:
- HINTERNET handle_;
-};
-
-// static
-bool HTTPUpload::SendRequest(const wstring &url,
- const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- int *timeout,
- wstring *response_body,
- int *response_code) {
- if (response_code) {
- *response_code = 0;
- }
-
- // TODO(bryner): support non-ASCII parameter names
- if (!CheckParameters(parameters)) {
- return false;
- }
-
- // Break up the URL and make sure we can handle it
- wchar_t scheme[16], host[256], path[256];
- URL_COMPONENTS components;
- memset(&components, 0, sizeof(components));
- components.dwStructSize = sizeof(components);
- components.lpszScheme = scheme;
- components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]);
- components.lpszHostName = host;
- components.dwHostNameLength = sizeof(host) / sizeof(host[0]);
- components.lpszUrlPath = path;
- components.dwUrlPathLength = sizeof(path) / sizeof(path[0]);
- if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
- 0, &components)) {
- return false;
- }
- bool secure = false;
- if (wcscmp(scheme, L"https") == 0) {
- secure = true;
- } else if (wcscmp(scheme, L"http") != 0) {
- return false;
- }
-
- AutoInternetHandle internet(InternetOpen(kUserAgent,
- INTERNET_OPEN_TYPE_PRECONFIG,
- NULL, // proxy name
- NULL, // proxy bypass
- 0)); // flags
- if (!internet.get()) {
- return false;
- }
-
- AutoInternetHandle connection(InternetConnect(internet.get(),
- host,
- components.nPort,
- NULL, // user name
- NULL, // password
- INTERNET_SERVICE_HTTP,
- 0, // flags
- NULL)); // context
- if (!connection.get()) {
- return false;
- }
-
- DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
- http_open_flags |= INTERNET_FLAG_NO_COOKIES;
- AutoInternetHandle request(HttpOpenRequest(connection.get(),
- L"POST",
- path,
- NULL, // version
- NULL, // referer
- NULL, // agent type
- http_open_flags,
- NULL)); // context
- if (!request.get()) {
- return false;
- }
-
- wstring boundary = GenerateMultipartBoundary();
- wstring content_type_header = GenerateRequestHeader(boundary);
- HttpAddRequestHeaders(request.get(),
- content_type_header.c_str(),
- static_cast<DWORD>(-1),
- HTTP_ADDREQ_FLAG_ADD);
-
- string request_body;
- if (!GenerateRequestBody(parameters, files, boundary, &request_body)) {
- return false;
- }
-
- if (timeout) {
- if (!InternetSetOption(request.get(),
- INTERNET_OPTION_SEND_TIMEOUT,
- timeout,
- sizeof(*timeout))) {
- fwprintf(stderr, L"Could not unset send timeout, continuing...\n");
- }
-
- if (!InternetSetOption(request.get(),
- INTERNET_OPTION_RECEIVE_TIMEOUT,
- timeout,
- sizeof(*timeout))) {
- fwprintf(stderr, L"Could not unset receive timeout, continuing...\n");
- }
- }
-
- if (!HttpSendRequest(request.get(), NULL, 0,
- const_cast<char *>(request_body.data()),
- static_cast<DWORD>(request_body.size()))) {
- return false;
- }
-
- // The server indicates a successful upload with HTTP status 200.
- wchar_t http_status[4];
- DWORD http_status_size = sizeof(http_status);
- if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
- static_cast<LPVOID>(&http_status), &http_status_size,
- 0)) {
- return false;
- }
-
- int http_response = wcstol(http_status, NULL, 10);
- if (response_code) {
- *response_code = http_response;
- }
-
- bool result = (http_response == 200);
-
- if (result) {
- result = ReadResponse(request.get(), response_body);
- }
-
- return result;
-}
-
-// static
-bool HTTPUpload::ReadResponse(HINTERNET request, wstring *response) {
- bool has_content_length_header = false;
- wchar_t content_length[32];
- DWORD content_length_size = sizeof(content_length);
- DWORD claimed_size = 0;
- string response_body;
-
- if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
- static_cast<LPVOID>(&content_length),
- &content_length_size, 0)) {
- has_content_length_header = true;
- claimed_size = wcstol(content_length, NULL, 10);
- response_body.reserve(claimed_size);
- }
-
-
- DWORD bytes_available;
- DWORD total_read = 0;
- BOOL return_code;
-
- while (((return_code = InternetQueryDataAvailable(request, &bytes_available,
- 0, 0)) != 0) && bytes_available > 0) {
- vector<char> response_buffer(bytes_available);
- DWORD size_read;
-
- return_code = InternetReadFile(request,
- &response_buffer[0],
- bytes_available, &size_read);
-
- if (return_code && size_read > 0) {
- total_read += size_read;
- response_body.append(&response_buffer[0], size_read);
- } else {
- break;
- }
- }
-
- bool succeeded = return_code && (!has_content_length_header ||
- (total_read == claimed_size));
- if (succeeded && response) {
- *response = UTF8ToWide(response_body);
- }
-
- return succeeded;
-}
-
-// static
-wstring HTTPUpload::GenerateMultipartBoundary() {
- // The boundary has 27 '-' characters followed by 16 hex digits
- static const wchar_t kBoundaryPrefix[] = L"---------------------------";
- static const int kBoundaryLength = 27 + 16 + 1;
-
- // Generate some random numbers to fill out the boundary
- int r0 = rand();
- int r1 = rand();
-
- wchar_t temp[kBoundaryLength];
- swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);
-
- // remove when VC++7.1 is no longer supported
- temp[kBoundaryLength - 1] = L'\0';
-
- return wstring(temp);
-}
-
-// static
-wstring HTTPUpload::GenerateRequestHeader(const wstring &boundary) {
- wstring header = L"Content-Type: multipart/form-data; boundary=";
- header += boundary;
- return header;
-}
-
-// static
-bool HTTPUpload::GenerateRequestBody(const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- const wstring &boundary,
- string *request_body) {
- string boundary_str = WideToUTF8(boundary);
- if (boundary_str.empty()) {
- return false;
- }
-
- request_body->clear();
-
- // Append each of the parameter pairs as a form-data part
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; name=\"" +
- WideToUTF8(pos->first) + "\"\r\n\r\n" +
- WideToUTF8(pos->second) + "\r\n");
- }
-
- for (map<wstring, wstring>::const_iterator pos = files.begin();
- pos != files.end(); ++pos) {
- vector<char> contents;
- if (!GetFileContents(pos->second, &contents)) {
- return false;
- }
-
- // Now append the upload files as a binary (octet-stream) part
- string filename_utf8 = WideToUTF8(pos->second);
- if (filename_utf8.empty()) {
- return false;
- }
-
- string file_part_name_utf8 = WideToUTF8(pos->first);
- if (file_part_name_utf8.empty()) {
- return false;
- }
-
- request_body->append("--" + boundary_str + "\r\n");
- request_body->append("Content-Disposition: form-data; "
- "name=\"" + file_part_name_utf8 + "\"; "
- "filename=\"" + filename_utf8 + "\"\r\n");
- request_body->append("Content-Type: application/octet-stream\r\n");
- request_body->append("\r\n");
-
- if (!contents.empty()) {
- request_body->append(&(contents[0]), contents.size());
- }
- request_body->append("\r\n");
- }
- request_body->append("--" + boundary_str + "--\r\n");
- return true;
-}
-
-// static
-bool HTTPUpload::GetFileContents(const wstring &filename,
- vector<char> *contents) {
- bool rv = false;
- // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
- // wchar_t* filename, so use _wfopen directly in that case. For VC8 and
- // later, _wfopen has been deprecated in favor of _wfopen_s, which does
- // not exist in earlier versions, so let the ifstream open the file itself.
- // GCC doesn't support wide file name and opening on FILE* requires ugly
- // hacks, so fallback to multi byte file.
-#ifdef _MSC_VER
- ifstream file;
- file.open(filename.c_str(), ios::binary);
-#else // GCC
- ifstream file(WideToMBCP(filename, CP_ACP).c_str(), ios::binary);
-#endif // _MSC_VER >= 1400
- if (file.is_open()) {
- file.seekg(0, ios::end);
- std::streamoff length = file.tellg();
- // Check for loss of data when converting lenght from std::streamoff into
- // std::vector<char>::size_type
- std::vector<char>::size_type vector_size =
- static_cast<std::vector<char>::size_type>(length);
- if (static_cast<std::streamoff>(vector_size) == length) {
- contents->resize(vector_size);
- if (length != 0) {
- file.seekg(0, ios::beg);
- file.read(&((*contents)[0]), length);
- }
- rv = true;
- }
- file.close();
- }
- return rv;
-}
-
-// static
-wstring HTTPUpload::UTF8ToWide(const string &utf8) {
- if (utf8.length() == 0) {
- return wstring();
- }
-
- // compute the length of the buffer we'll need
- int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
-
- if (charcount == 0) {
- return wstring();
- }
-
- // convert
- wchar_t* buf = new wchar_t[charcount];
- MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
- wstring result(buf);
- delete[] buf;
- return result;
-}
-
-// static
-string HTTPUpload::WideToMBCP(const wstring &wide, unsigned int cp) {
- if (wide.length() == 0) {
- return string();
- }
-
- // compute the length of the buffer we'll need
- int charcount = WideCharToMultiByte(cp, 0, wide.c_str(), -1,
- NULL, 0, NULL, NULL);
- if (charcount == 0) {
- return string();
- }
-
- // convert
- char *buf = new char[charcount];
- WideCharToMultiByte(cp, 0, wide.c_str(), -1, buf, charcount,
- NULL, NULL);
-
- string result(buf);
- delete[] buf;
- return result;
-}
-
-// static
-bool HTTPUpload::CheckParameters(const map<wstring, wstring> &parameters) {
- for (map<wstring, wstring>::const_iterator pos = parameters.begin();
- pos != parameters.end(); ++pos) {
- const wstring &str = pos->first;
- if (str.size() == 0) {
- return false; // disallow empty parameter names
- }
- for (unsigned int i = 0; i < str.size(); ++i) {
- wchar_t c = str[i];
- if (c < 32 || c == '"' || c > 127) {
- return false;
- }
- }
- }
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h b/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
deleted file mode 100644
index f8d48cb1b..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/http_upload.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// HTTPUpload provides a "nice" API to send a multipart HTTP(S) POST
-// request using wininet. It currently supports requests that contain
-// a set of string parameters (key/value pairs), and a file to upload.
-
-#ifndef COMMON_WINDOWS_HTTP_UPLOAD_H_
-#define COMMON_WINDOWS_HTTP_UPLOAD_H_
-
-#pragma warning(push)
-// Disable exception handler warnings.
-#pragma warning(disable : 4530)
-
-#include <windows.h>
-#include <wininet.h>
-
-#include <map>
-#include <string>
-#include <vector>
-
-namespace google_breakpad {
-
-using std::string;
-using std::wstring;
-using std::map;
-using std::vector;
-
-class HTTPUpload {
- public:
- // Sends the given sets of parameters and files as a multipart POST
- // request to the given URL.
- // Each key in |files| is the name of the file part of the request
- // (i.e. it corresponds to the name= attribute on an <input type="file">.
- // Parameter names must contain only printable ASCII characters,
- // and may not contain a quote (") character.
- // Only HTTP(S) URLs are currently supported. Returns true on success.
- // If the request is successful and response_body is non-NULL,
- // the response body will be returned in response_body.
- // If response_code is non-NULL, it will be set to the HTTP response code
- // received (or 0 if the request failed before getting an HTTP response).
- static bool SendRequest(const wstring &url,
- const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- int *timeout,
- wstring *response_body,
- int *response_code);
-
- private:
- class AutoInternetHandle;
-
- // Retrieves the HTTP response. If NULL is passed in for response,
- // this merely checks (via the return value) that we were successfully
- // able to retrieve exactly as many bytes of content in the response as
- // were specified in the Content-Length header.
- static bool ReadResponse(HINTERNET request, wstring* response);
-
- // Generates a new multipart boundary for a POST request
- static wstring GenerateMultipartBoundary();
-
- // Generates a HTTP request header for a multipart form submit.
- static wstring GenerateRequestHeader(const wstring &boundary);
-
- // Given a set of parameters, a set of upload files, and a file part name,
- // generates a multipart request body string with these parameters
- // and minidump contents. Returns true on success.
- static bool GenerateRequestBody(const map<wstring, wstring> &parameters,
- const map<wstring, wstring> &files,
- const wstring &boundary,
- string *request_body);
-
- // Fills the supplied vector with the contents of filename.
- static bool GetFileContents(const wstring &filename, vector<char> *contents);
-
- // Converts a UTF8 string to UTF16.
- static wstring UTF8ToWide(const string &utf8);
-
- // Converts a UTF16 string to UTF8.
- static string WideToUTF8(const wstring &wide) {
- return WideToMBCP(wide, CP_UTF8);
- }
-
- // Converts a UTF16 string to specified code page.
- static string WideToMBCP(const wstring &wide, unsigned int cp);
-
- // Checks that the given list of parameters has only printable
- // ASCII characters in the parameter name, and does not contain
- // any quote (") characters. Returns true if so.
- static bool CheckParameters(const map<wstring, wstring> &parameters);
-
- // No instances of this class should be created.
- // Disallow all constructors, destructors, and operator=.
- HTTPUpload();
- explicit HTTPUpload(const HTTPUpload &);
- void operator=(const HTTPUpload &);
- ~HTTPUpload();
-};
-
-} // namespace google_breakpad
-
-#pragma warning(pop)
-
-#endif // COMMON_WINDOWS_HTTP_UPLOAD_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild b/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
deleted file mode 100644
index 5fcdae5a3..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-lobjs_common = [
- 'guid_string.cc',
- 'string_utils.cc',
-]
-
-subdir = 'toolkit/crashreporter/google-breakpad/src/common/windows'
-objs_common = [
- '/%s/%s' % (subdir, s) for s in lobjs_common
-]
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
deleted file mode 100644
index 554a57c2d..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.cc
+++ /dev/null
@@ -1,694 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// This contains a suite of tools for transforming symbol information when
-// when that information has been extracted from a PDB containing OMAP
-// information.
-
-// OMAP information is a lightweight description of a mapping between two
-// address spaces. It consists of two streams, each of them a vector 2-tuples.
-// The OMAPTO stream contains tuples of the form
-//
-// (RVA in transformed image, RVA in original image)
-//
-// while the OMAPFROM stream contains tuples of the form
-//
-// (RVA in original image, RVA in transformed image)
-//
-// The entries in each vector are sorted by the first value of the tuple, and
-// the lengths associated with a mapping are implicit as the distance between
-// two successive addresses in the vector.
-
-// Consider a trivial 10-byte function described by the following symbol:
-//
-// Function: RVA 0x00001000, length 10, "foo"
-//
-// Now consider the same function, but with 5-bytes of instrumentation injected
-// at offset 5. The OMAP streams describing this would look like:
-//
-// OMAPTO : [ [0x00001000, 0x00001000],
-// [0x00001005, 0xFFFFFFFF],
-// [0x0000100a, 0x00001005] ]
-// OMAPFROM: [ [0x00001000, 0x00001000],
-// [0x00001005, 0x0000100a] ]
-//
-// In this case the injected code has been marked as not originating in the
-// source image, and thus it will have no symbol information at all. However,
-// the injected code may also be associated with an original address range;
-// for example, when prepending instrumentation to a basic block the
-// instrumentation can be labelled as originating from the same source BB such
-// that symbol resolution will still find the appropriate source code line
-// number. In this case the OMAP stream would look like:
-//
-// OMAPTO : [ [0x00001000, 0x00001000],
-// [0x00001005, 0x00001005],
-// [0x0000100a, 0x00001005] ]
-// OMAPFROM: [ [0x00001000, 0x00001000],
-// [0x00001005, 0x0000100a] ]
-//
-// Suppose we asked DIA to lookup the symbol at location 0x0000100a of the
-// instrumented image. It would first run this through the OMAPTO table and
-// translate that address to 0x00001005. It would then lookup the symbol
-// at that address and return the symbol for the function "foo". This is the
-// correct result.
-//
-// However, if we query DIA for the length and address of the symbol it will
-// tell us that it has length 10 and is at RVA 0x00001000. The location is
-// correct, but the length doesn't take into account the 5-bytes of injected
-// code. Symbol resolution works (starting from an instrumented address,
-// mapping to an original address, and looking up a symbol), but the symbol
-// metadata is incorrect.
-//
-// If we dump the symbols using DIA they will have their addresses
-// appropriately transformed and reflect positions in the instrumented image.
-// However, if we try to do a lookup using those symbols resolution can fail.
-// For example, the address 0x0000100a will not map to the symbol for "foo",
-// because DIA tells us it is at location 0x00001000 (correct) with length
-// 10 (incorrect). The problem is one of order of operations: in this case
-// we're attempting symbol resolution by looking up an instrumented address
-// in the table of translated symbols.
-//
-// One way to handle this is to dump the OMAP information as part of the
-// breakpad symbols. This requires the rest of the toolchain to be aware of
-// OMAP information and to use it when present prior to performing lookup. The
-// other option is to properly transform the symbols (updating length as well as
-// position) so that resolution will work as expected for translated addresses.
-// This is transparent to the rest of the toolchain.
-
-#include "common/windows/omap.h"
-
-#include <atlbase.h>
-
-#include <algorithm>
-#include <cassert>
-#include <set>
-
-#include "common/windows/dia_util.h"
-
-namespace google_breakpad {
-
-namespace {
-
-static const wchar_t kOmapToDebugStreamName[] = L"OMAPTO";
-static const wchar_t kOmapFromDebugStreamName[] = L"OMAPFROM";
-
-// Dependending on where this is used in breakpad we sometimes get min/max from
-// windef, and other times from algorithm. To get around this we simply
-// define our own min/max functions.
-template<typename T>
-const T& Min(const T& t1, const T& t2) { return t1 < t2 ? t1 : t2; }
-template<typename T>
-const T& Max(const T& t1, const T& t2) { return t1 > t2 ? t1 : t2; }
-
-// It makes things more readable to have two different OMAP types. We cast
-// normal OMAPs into these. They must be the same size as the OMAP structure
-// for this to work, hence the static asserts.
-struct OmapOrigToTran {
- DWORD rva_original;
- DWORD rva_transformed;
-};
-struct OmapTranToOrig {
- DWORD rva_transformed;
- DWORD rva_original;
-};
-static_assert(sizeof(OmapOrigToTran) == sizeof(OMAP),
- "OmapOrigToTran must have same size as OMAP.");
-static_assert(sizeof(OmapTranToOrig) == sizeof(OMAP),
- "OmapTranToOrig must have same size as OMAP.");
-typedef std::vector<OmapOrigToTran> OmapFromTable;
-typedef std::vector<OmapTranToOrig> OmapToTable;
-
-// Used for sorting and searching through a Mapping.
-bool MappedRangeOriginalLess(const MappedRange& lhs, const MappedRange& rhs) {
- if (lhs.rva_original < rhs.rva_original)
- return true;
- if (lhs.rva_original > rhs.rva_original)
- return false;
- return lhs.length < rhs.length;
-}
-bool MappedRangeMappedLess(const MappedRange& lhs, const MappedRange& rhs) {
- if (lhs.rva_transformed < rhs.rva_transformed)
- return true;
- if (lhs.rva_transformed > rhs.rva_transformed)
- return false;
- return lhs.length < rhs.length;
-}
-
-// Used for searching through the EndpointIndexMap.
-bool EndpointIndexLess(const EndpointIndex& ei1, const EndpointIndex& ei2) {
- return ei1.endpoint < ei2.endpoint;
-}
-
-// Finds the debug stream with the given |name| in the given |session|, and
-// populates |table| with its contents. Casts the data directly into OMAP
-// structs.
-bool FindAndLoadOmapTable(const wchar_t* name,
- IDiaSession* session,
- OmapTable* table) {
- assert(name != NULL);
- assert(session != NULL);
- assert(table != NULL);
-
- CComPtr<IDiaEnumDebugStreamData> stream;
- if (!FindDebugStream(name, session, &stream))
- return false;
- assert(stream.p != NULL);
-
- LONG count = 0;
- if (FAILED(stream->get_Count(&count))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::get_Count failed for stream "
- "\"%ws\"\n", name);
- return false;
- }
-
- // Get the length of the stream in bytes.
- DWORD bytes_read = 0;
- ULONG count_read = 0;
- if (FAILED(stream->Next(count, 0, &bytes_read, NULL, &count_read))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
- "length of stream \"%ws\"\n", name);
- return false;
- }
-
- // Ensure it's consistent with the OMAP data type.
- DWORD bytes_expected = count * sizeof(OmapTable::value_type);
- if (count * sizeof(OmapTable::value_type) != bytes_read) {
- fprintf(stderr, "DIA debug stream \"%ws\" has an unexpected length", name);
- return false;
- }
-
- // Read the table.
- table->resize(count);
- bytes_read = 0;
- count_read = 0;
- if (FAILED(stream->Next(count, bytes_expected, &bytes_read,
- reinterpret_cast<BYTE*>(&table->at(0)),
- &count_read))) {
- fprintf(stderr, "IDiaEnumDebugStreamData::Next failed while reading "
- "data from stream \"%ws\"\n", name);
- return false;
- }
-
- return true;
-}
-
-// This determines the original image length by looking through the segment
-// table.
-bool GetOriginalImageLength(IDiaSession* session, DWORD* image_length) {
- assert(session != NULL);
- assert(image_length != NULL);
-
- CComPtr<IDiaEnumSegments> enum_segments;
- if (!FindTable(session, &enum_segments))
- return false;
- assert(enum_segments.p != NULL);
-
- DWORD temp_image_length = 0;
- CComPtr<IDiaSegment> segment;
- ULONG fetched = 0;
- while (SUCCEEDED(enum_segments->Next(1, &segment, &fetched)) &&
- fetched == 1) {
- assert(segment.p != NULL);
-
- DWORD rva = 0;
- DWORD length = 0;
- DWORD frame = 0;
- if (FAILED(segment->get_relativeVirtualAddress(&rva)) ||
- FAILED(segment->get_length(&length)) ||
- FAILED(segment->get_frame(&frame))) {
- fprintf(stderr, "Failed to get basic properties for IDiaSegment\n");
- return false;
- }
-
- if (frame > 0) {
- DWORD segment_end = rva + length;
- if (segment_end > temp_image_length)
- temp_image_length = segment_end;
- }
- segment.Release();
- }
-
- *image_length = temp_image_length;
- return true;
-}
-
-// Detects regions of the original image that have been removed in the
-// transformed image, and sets the 'removed' property on all mapped ranges
-// immediately preceding a gap. The mapped ranges must be sorted by
-// 'rva_original'.
-void FillInRemovedLengths(Mapping* mapping) {
- assert(mapping != NULL);
-
- // Find and fill gaps. We do this with two sweeps. We first sweep forward
- // looking for gaps. When we identify a gap we then sweep forward with a
- // second scan and set the 'removed' property for any intervals that
- // immediately precede the gap.
- //
- // Gaps are typically between two successive intervals, but not always:
- //
- // Range 1: ---------------
- // Range 2: -------
- // Range 3: -------------
- // Gap : ******
- //
- // In the above example the gap is between range 1 and range 3. A forward
- // sweep finds the gap, and a second forward sweep identifies that range 1
- // immediately precedes the gap and sets its 'removed' property.
-
- size_t fill = 0;
- DWORD rva_front = 0;
- for (size_t find = 0; find < mapping->size(); ++find) {
-#ifndef NDEBUG
- // We expect the mapped ranges to be sorted by 'rva_original'.
- if (find > 0) {
- assert(mapping->at(find - 1).rva_original <=
- mapping->at(find).rva_original);
- }
-#endif
-
- if (rva_front < mapping->at(find).rva_original) {
- // We've found a gap. Fill it in by setting the 'removed' property for
- // any affected intervals.
- DWORD removed = mapping->at(find).rva_original - rva_front;
- for (; fill < find; ++fill) {
- if (mapping->at(fill).rva_original + mapping->at(fill).length !=
- rva_front) {
- continue;
- }
-
- // This interval ends right where the gap starts. It needs to have its
- // 'removed' information filled in.
- mapping->at(fill).removed = removed;
- }
- }
-
- // Advance the front that indicates the covered portion of the image.
- rva_front = mapping->at(find).rva_original + mapping->at(find).length;
- }
-}
-
-// Builds a unified view of the mapping between the original and transformed
-// image space by merging OMAPTO and OMAPFROM data.
-void BuildMapping(const OmapData& omap_data, Mapping* mapping) {
- assert(mapping != NULL);
-
- mapping->clear();
-
- if (omap_data.omap_from.empty() || omap_data.omap_to.empty())
- return;
-
- // The names 'omap_to' and 'omap_from' are awfully confusing, so we make
- // ourselves more explicit here. This cast is only safe because the underlying
- // types have the exact same size.
- const OmapToTable& tran2orig =
- reinterpret_cast<const OmapToTable&>(omap_data.omap_to);
- const OmapFromTable& orig2tran = reinterpret_cast<const OmapFromTable&>(
- omap_data.omap_from);
-
- // Handle the range of data at the beginning of the image. This is not usually
- // specified by the OMAP data.
- if (tran2orig[0].rva_transformed > 0 && orig2tran[0].rva_original > 0) {
- DWORD header_transformed = tran2orig[0].rva_transformed;
- DWORD header_original = orig2tran[0].rva_original;
- DWORD header = Min(header_transformed, header_original);
-
- MappedRange mr = {};
- mr.length = header;
- mr.injected = header_transformed - header;
- mr.removed = header_original - header;
- mapping->push_back(mr);
- }
-
- // Convert the implied lengths to explicit lengths, and infer which content
- // has been injected into the transformed image. Injected content is inferred
- // as regions of the transformed address space that does not map back to
- // known valid content in the original image.
- for (size_t i = 0; i < tran2orig.size(); ++i) {
- const OmapTranToOrig& o1 = tran2orig[i];
-
- // This maps to content that is outside the original image, thus it
- // describes injected content. We can skip this entry.
- if (o1.rva_original >= omap_data.length_original)
- continue;
-
- // Calculate the length of the current OMAP entry. This is implicit as the
- // distance between successive |rva| values, capped at the end of the
- // original image.
- DWORD length = 0;
- if (i + 1 < tran2orig.size()) {
- const OmapTranToOrig& o2 = tran2orig[i + 1];
-
- // We expect the table to be sorted by rva_transformed.
- assert(o1.rva_transformed <= o2.rva_transformed);
-
- length = o2.rva_transformed - o1.rva_transformed;
- if (o1.rva_original + length > omap_data.length_original) {
- length = omap_data.length_original - o1.rva_original;
- }
- } else {
- length = omap_data.length_original - o1.rva_original;
- }
-
- // Zero-length entries don't describe anything and can be ignored.
- if (length == 0)
- continue;
-
- // Any gaps in the transformed address-space are due to injected content.
- if (!mapping->empty()) {
- MappedRange& prev_mr = mapping->back();
- prev_mr.injected += o1.rva_transformed -
- (prev_mr.rva_transformed + prev_mr.length);
- }
-
- MappedRange mr = {};
- mr.rva_original = o1.rva_original;
- mr.rva_transformed = o1.rva_transformed;
- mr.length = length;
- mapping->push_back(mr);
- }
-
- // Sort based on the original image addresses.
- std::sort(mapping->begin(), mapping->end(), MappedRangeOriginalLess);
-
- // Fill in the 'removed' lengths by looking for gaps in the coverage of the
- // original address space.
- FillInRemovedLengths(mapping);
-
- return;
-}
-
-void BuildEndpointIndexMap(ImageMap* image_map) {
- assert(image_map != NULL);
-
- if (image_map->mapping.size() == 0)
- return;
-
- const Mapping& mapping = image_map->mapping;
- EndpointIndexMap& eim = image_map->endpoint_index_map;
-
- // Get the unique set of interval endpoints.
- std::set<DWORD> endpoints;
- for (size_t i = 0; i < mapping.size(); ++i) {
- endpoints.insert(mapping[i].rva_original);
- endpoints.insert(mapping[i].rva_original +
- mapping[i].length +
- mapping[i].removed);
- }
-
- // Use the endpoints to initialize the secondary search structure for the
- // mapping.
- eim.resize(endpoints.size());
- std::set<DWORD>::const_iterator it = endpoints.begin();
- for (size_t i = 0; it != endpoints.end(); ++it, ++i) {
- eim[i].endpoint = *it;
- eim[i].index = mapping.size();
- }
-
- // For each endpoint we want the smallest index of any interval containing
- // it. We iterate over the intervals and update the indices associated with
- // each interval endpoint contained in the current interval. In the general
- // case of an arbitrary set of intervals this is O(n^2), but the structure of
- // OMAP data makes this O(n).
- for (size_t i = 0; i < mapping.size(); ++i) {
- EndpointIndex ei1 = { mapping[i].rva_original, 0 };
- EndpointIndexMap::iterator it1 = std::lower_bound(
- eim.begin(), eim.end(), ei1, EndpointIndexLess);
-
- EndpointIndex ei2 = { mapping[i].rva_original + mapping[i].length +
- mapping[i].removed, 0 };
- EndpointIndexMap::iterator it2 = std::lower_bound(
- eim.begin(), eim.end(), ei2, EndpointIndexLess);
-
- for (; it1 != it2; ++it1)
- it1->index = Min(i, it1->index);
- }
-}
-
-// Clips the given mapped range.
-void ClipMappedRangeOriginal(const AddressRange& clip_range,
- MappedRange* mapped_range) {
- assert(mapped_range != NULL);
-
- // The clipping range is entirely outside of the mapped range.
- if (clip_range.end() <= mapped_range->rva_original ||
- mapped_range->rva_original + mapped_range->length +
- mapped_range->removed <= clip_range.rva) {
- mapped_range->length = 0;
- mapped_range->injected = 0;
- mapped_range->removed = 0;
- return;
- }
-
- // Clip the left side.
- if (mapped_range->rva_original < clip_range.rva) {
- DWORD clip_left = clip_range.rva - mapped_range->rva_original;
- mapped_range->rva_original += clip_left;
- mapped_range->rva_transformed += clip_left;
-
- if (clip_left > mapped_range->length) {
- // The left clipping boundary entirely erases the content section of the
- // range.
- DWORD trim = clip_left - mapped_range->length;
- mapped_range->length = 0;
- mapped_range->injected -= Min(trim, mapped_range->injected);
- // We know that trim <= mapped_range->remove.
- mapped_range->removed -= trim;
- } else {
- // The left clipping boundary removes some, but not all, of the content.
- // As such it leaves the removed/injected component intact.
- mapped_range->length -= clip_left;
- }
- }
-
- // Clip the right side.
- DWORD end_original = mapped_range->rva_original + mapped_range->length;
- if (clip_range.end() < end_original) {
- // The right clipping boundary lands in the 'content' section of the range,
- // entirely clearing the injected/removed portion.
- DWORD clip_right = end_original - clip_range.end();
- mapped_range->length -= clip_right;
- mapped_range->injected = 0;
- mapped_range->removed = 0;
- return;
- } else {
- // The right clipping boundary is outside of the content, but may affect
- // the removed/injected portion of the range.
- DWORD end_removed = end_original + mapped_range->removed;
- if (clip_range.end() < end_removed)
- mapped_range->removed = clip_range.end() - end_original;
-
- DWORD end_injected = end_original + mapped_range->injected;
- if (clip_range.end() < end_injected)
- mapped_range->injected = clip_range.end() - end_original;
- }
-
- return;
-}
-
-} // namespace
-
-int AddressRange::Compare(const AddressRange& rhs) const {
- if (end() <= rhs.rva)
- return -1;
- if (rhs.end() <= rva)
- return 1;
- return 0;
-}
-
-bool GetOmapDataAndDisableTranslation(IDiaSession* session,
- OmapData* omap_data) {
- assert(session != NULL);
- assert(omap_data != NULL);
-
- CComPtr<IDiaAddressMap> address_map;
- if (FAILED(session->QueryInterface(&address_map))) {
- fprintf(stderr, "IDiaSession::QueryInterface(IDiaAddressMap) failed\n");
- return false;
- }
- assert(address_map.p != NULL);
-
- BOOL omap_enabled = FALSE;
- if (FAILED(address_map->get_addressMapEnabled(&omap_enabled))) {
- fprintf(stderr, "IDiaAddressMap::get_addressMapEnabled failed\n");
- return false;
- }
-
- if (!omap_enabled) {
- // We indicate the non-presence of OMAP data by returning empty tables.
- omap_data->omap_from.clear();
- omap_data->omap_to.clear();
- omap_data->length_original = 0;
- return true;
- }
-
- // OMAP data is present. Disable translation.
- if (FAILED(address_map->put_addressMapEnabled(FALSE))) {
- fprintf(stderr, "IDiaAddressMap::put_addressMapEnabled failed\n");
- return false;
- }
-
- // Read the OMAP streams.
- if (!FindAndLoadOmapTable(kOmapFromDebugStreamName,
- session,
- &omap_data->omap_from)) {
- return false;
- }
- if (!FindAndLoadOmapTable(kOmapToDebugStreamName,
- session,
- &omap_data->omap_to)) {
- return false;
- }
-
- // Get the lengths of the address spaces.
- if (!GetOriginalImageLength(session, &omap_data->length_original))
- return false;
-
- return true;
-}
-
-void BuildImageMap(const OmapData& omap_data, ImageMap* image_map) {
- assert(image_map != NULL);
-
- BuildMapping(omap_data, &image_map->mapping);
- BuildEndpointIndexMap(image_map);
-}
-
-void MapAddressRange(const ImageMap& image_map,
- const AddressRange& original_range,
- AddressRangeVector* mapped_ranges) {
- assert(mapped_ranges != NULL);
-
- const Mapping& map = image_map.mapping;
-
- // Handle the trivial case of an empty image_map. This means that there is
- // no transformation to be applied, and we can simply return the original
- // range.
- if (map.empty()) {
- mapped_ranges->push_back(original_range);
- return;
- }
-
- // If we get a query of length 0 we need to handle it by using a non-zero
- // query length.
- AddressRange query_range(original_range);
- if (query_range.length == 0)
- query_range.length = 1;
-
- // Find the range of intervals that can potentially intersect our query range.
- size_t imin = 0;
- size_t imax = 0;
- {
- // The index of the earliest possible range that can affect is us done by
- // searching through the secondary indexing structure.
- const EndpointIndexMap& eim = image_map.endpoint_index_map;
- EndpointIndex q1 = { query_range.rva, 0 };
- EndpointIndexMap::const_iterator it1 = std::lower_bound(
- eim.begin(), eim.end(), q1, EndpointIndexLess);
- if (it1 == eim.end()) {
- imin = map.size();
- } else {
- // Backup to find the interval that contains our query point.
- if (it1 != eim.begin() && query_range.rva < it1->endpoint)
- --it1;
- imin = it1->index;
- }
-
- // The first range that can't possibly intersect us is found by searching
- // through the image map directly as it is already sorted by interval start
- // point.
- MappedRange q2 = { query_range.end(), 0 };
- Mapping::const_iterator it2 = std::lower_bound(
- map.begin(), map.end(), q2, MappedRangeOriginalLess);
- imax = it2 - map.begin();
- }
-
- // Find all intervals that intersect the query range.
- Mapping temp_map;
- for (size_t i = imin; i < imax; ++i) {
- MappedRange mr = map[i];
- ClipMappedRangeOriginal(query_range, &mr);
- if (mr.length + mr.injected > 0)
- temp_map.push_back(mr);
- }
-
- // If there are no intersecting ranges then the query range has been removed
- // from the image in question.
- if (temp_map.empty())
- return;
-
- // Sort based on transformed addresses.
- std::sort(temp_map.begin(), temp_map.end(), MappedRangeMappedLess);
-
- // Zero-length queries can't actually be merged. We simply output the set of
- // unique RVAs that correspond to the query RVA.
- if (original_range.length == 0) {
- mapped_ranges->push_back(AddressRange(temp_map[0].rva_transformed, 0));
- for (size_t i = 1; i < temp_map.size(); ++i) {
- if (temp_map[i].rva_transformed > mapped_ranges->back().rva)
- mapped_ranges->push_back(AddressRange(temp_map[i].rva_transformed, 0));
- }
- return;
- }
-
- // Merge any ranges that are consecutive in the mapped image. We merge over
- // injected content if it makes ranges contiguous, but we ignore any injected
- // content at the tail end of a range. This allows us to detect symbols that
- // have been lengthened by injecting content in the middle. However, it
- // misses the case where content has been injected at the head or the tail.
- // The problem is that it doesn't know whether to attribute it to the
- // preceding or following symbol. It is up to the author of the transform to
- // output explicit OMAP info in these cases to ensure full coverage of the
- // transformed address space.
- DWORD rva_begin = temp_map[0].rva_transformed;
- DWORD rva_cur_content = rva_begin + temp_map[0].length;
- DWORD rva_cur_injected = rva_cur_content + temp_map[0].injected;
- for (size_t i = 1; i < temp_map.size(); ++i) {
- if (rva_cur_injected < temp_map[i].rva_transformed) {
- // This marks the end of a continuous range in the image. Output the
- // current range and start a new one.
- if (rva_begin < rva_cur_content) {
- mapped_ranges->push_back(
- AddressRange(rva_begin, rva_cur_content - rva_begin));
- }
- rva_begin = temp_map[i].rva_transformed;
- }
-
- rva_cur_content = temp_map[i].rva_transformed + temp_map[i].length;
- rva_cur_injected = rva_cur_content + temp_map[i].injected;
- }
-
- // Output the range in progress.
- if (rva_begin < rva_cur_content) {
- mapped_ranges->push_back(
- AddressRange(rva_begin, rva_cur_content - rva_begin));
- }
-
- return;
-}
-
-} // namespace google_breakpad \ No newline at end of file
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h b/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
deleted file mode 100644
index bc293afb5..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Provides an API for mapping symbols through OMAP information, if a PDB file
-// is augmented with it. This allows breakpad to work with addresses in
-// transformed images by transforming the symbols themselves, rather than
-// transforming addresses prior to querying symbols (the way it is typically
-// done by Windows-native tools, including the DIA).
-
-#ifndef COMMON_WINDOWS_OMAP_H_
-#define COMMON_WINDOWS_OMAP_H_
-
-#include "common/windows/omap_internal.h"
-
-namespace google_breakpad {
-
-// If the given session contains OMAP data this extracts it, populating
-// |omap_data|, and then disabling automatic translation for the session.
-// OMAP data is present in the PDB if |omap_data| is not empty. This returns
-// true on success, false otherwise.
-bool GetOmapDataAndDisableTranslation(IDiaSession* dia_session,
- OmapData* omap_data);
-
-// Given raw OMAP data builds an ImageMap. This can be used to query individual
-// image ranges using MapAddressRange.
-// |omap_data|| is the OMAP data extracted from the PDB.
-// |image_map| will be populated with a description of the image mapping. If
-// |omap_data| is empty then this will also be empty.
-void BuildImageMap(const OmapData& omap_data, ImageMap* image_map);
-
-// Given an address range in the original image space determines how exactly it
-// has been tranformed.
-// |omap_data| is the OMAP data extracted from the PDB, which must not be
-// empty.
-// |original_range| is the address range in the original image being queried.
-// |mapped_ranges| will be populated with a full description of the mapping.
-// They may be disjoint in the transformed image so a vector is needed to
-// fully represent the mapping. This will be appended to if it is not
-// empty. If |omap_data| is empty then |mapped_ranges| will simply be
-// populated with a copy of |original_range| (the identity transform).
-void MapAddressRange(const ImageMap& image_map,
- const AddressRange& original_range,
- AddressRangeVector* mapped_ranges);
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_OMAP_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
deleted file mode 100644
index 3f904d7a7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_internal.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Declares internal implementation details for functionality in omap.h and
-// omap.cc.
-
-#ifndef COMMON_WINDOWS_OMAP_INTERNAL_H_
-#define COMMON_WINDOWS_OMAP_INTERNAL_H_
-
-#include <windows.h>
-#include <dia2.h>
-
-#include <vector>
-
-namespace google_breakpad {
-
-// The OMAP struct is defined by debughlp.h, which doesn't play nicely with
-// imagehlp.h. We simply redefine it.
-struct OMAP {
- DWORD rva;
- DWORD rvaTo;
-};
-static_assert(sizeof(OMAP) == 8, "Wrong size for OMAP structure.");
-typedef std::vector<OMAP> OmapTable;
-
-// This contains the OMAP data extracted from an image.
-struct OmapData {
- // The table of OMAP entries describing the transformation from the
- // original image to the transformed image.
- OmapTable omap_from;
- // The table of OMAP entries describing the transformation from the
- // instrumented image to the original image.
- OmapTable omap_to;
- // The length of the original untransformed image.
- DWORD length_original;
-
- OmapData() : length_original(0) { }
-};
-
-// This represents a range of addresses in an image.
-struct AddressRange {
- DWORD rva;
- DWORD length;
-
- AddressRange() : rva(0), length(0) { }
- AddressRange(DWORD rva, DWORD length) : rva(rva), length(length) { }
-
- // Returns the end address of this range.
- DWORD end() const { return rva + length; }
-
- // Addreses only compare as less-than or greater-than if they are not
- // overlapping. Otherwise, they compare equal.
- int Compare(const AddressRange& rhs) const;
- bool operator<(const AddressRange& rhs) const { return Compare(rhs) == -1; }
- bool operator>(const AddressRange& rhs) const { return Compare(rhs) == 1; }
-
- // Equality operators compare exact values.
- bool operator==(const AddressRange& rhs) const {
- return rva == rhs.rva && length == rhs.length;
- }
- bool operator!=(const AddressRange& rhs) const { return !((*this) == rhs); }
-};
-
-typedef std::vector<AddressRange> AddressRangeVector;
-
-// This represents an address range in an original image, and its corresponding
-// range in the transformed image.
-struct MappedRange {
- // An address in the original image.
- DWORD rva_original;
- // The corresponding addresses in the transformed image.
- DWORD rva_transformed;
- // The length of the address range.
- DWORD length;
- // It is possible for code to be injected into a transformed image, for which
- // there is no corresponding code in the original image. If this range of
- // transformed image is immediately followed by such injected code we maintain
- // a record of its length here.
- DWORD injected;
- // It is possible for code to be removed from the original image. This happens
- // for things like padding between blocks. There is no actual content lost,
- // but the spacing between items may be lost. This keeps track of any removed
- // content immediately following the |original| range.
- DWORD removed;
-};
-// A vector of mapped ranges is used as a more useful representation of
-// OMAP data.
-typedef std::vector<MappedRange> Mapping;
-
-// Used as a secondary search structure accompanying a Mapping.
-struct EndpointIndex {
- DWORD endpoint;
- size_t index;
-};
-typedef std::vector<EndpointIndex> EndpointIndexMap;
-
-// An ImageMap is vector of mapped ranges, plus a secondary index into it for
-// doing interval searches. (An interval tree would also work, but is overkill
-// because we don't need insertion and deletion.)
-struct ImageMap {
- // This is a description of the mapping between original and transformed
- // image, sorted by addresses in the original image.
- Mapping mapping;
- // For all interval endpoints in |mapping| this stores the minimum index of
- // an interval in |mapping| that contains the endpoint. Useful for doing
- // interval intersection queries.
- EndpointIndexMap endpoint_index_map;
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_OMAP_INTERNAL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
deleted file mode 100644
index 960a33f46..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/omap_unittest.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2013 Google Inc. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Unittests for OMAP related functions.
-
-#include "common/windows/omap.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-
-namespace google_breakpad {
-
-// Equality operators for ContainerEq. These must be outside of the anonymous
-// namespace in order for them to be found.
-bool operator==(const MappedRange& mr1, const MappedRange& mr2) {
- return mr1.rva_original == mr2.rva_original &&
- mr1.rva_transformed == mr2.rva_transformed &&
- mr1.length == mr2.length &&
- mr1.injected == mr2.injected &&
- mr1.removed == mr2.removed;
-}
-bool operator==(const EndpointIndex& ei1, const EndpointIndex& ei2) {
- return ei1.endpoint == ei2.endpoint && ei1.index == ei2.index;
-}
-
-// Pretty printers for more meaningful error messages. Also need to be outside
-// the anonymous namespace.
-std::ostream& operator<<(std::ostream& os, const MappedRange& mr) {
- os << "MappedRange(rva_original=" << mr.rva_original
- << ", rva_transformed=" << mr.rva_transformed
- << ", length=" << mr.length
- << ", injected=" << mr.injected
- << ", removed=" << mr.removed << ")";
- return os;
-}
-std::ostream& operator<<(std::ostream& os, const EndpointIndex& ei) {
- os << "EndpointIndex(endpoint=" << ei.endpoint
- << ", index=" << ei.index << ")";
- return os;
-}
-std::ostream& operator<<(std::ostream& os, const AddressRange& ar) {
- os << "AddressRange(rva=" << ar.rva << ", length=" << ar.length << ")";
- return os;
-}
-
-namespace {
-
-OMAP CreateOmap(DWORD rva, DWORD rvaTo) {
- OMAP o = { rva, rvaTo };
- return o;
-}
-
-MappedRange CreateMappedRange(DWORD rva_original,
- DWORD rva_transformed,
- DWORD length,
- DWORD injected,
- DWORD removed) {
- MappedRange mr = { rva_original, rva_transformed, length, injected, removed };
- return mr;
-}
-
-EndpointIndex CreateEndpointIndex(DWORD endpoint, size_t index) {
- EndpointIndex ei = { endpoint, index };
- return ei;
-}
-
-// (C is removed)
-// Original : A B C D E F G H
-// Transformed: A B D F E * H1 G1 G2 H2
-// (* is injected, G is copied, H is split)
-// A is implied.
-
-// Layout of the original image.
-const AddressRange B(100, 15);
-const AddressRange C(B.end(), 10);
-const AddressRange D(C.end(), 25);
-const AddressRange E(D.end(), 10);
-const AddressRange F(E.end(), 40);
-const AddressRange G(F.end(), 3);
-const AddressRange H(G.end(), 7);
-
-// Layout of the transformed image.
-const AddressRange Bt(100, 15);
-const AddressRange Dt(Bt.end(), 20); // D is shortened.
-const AddressRange Ft(Dt.end(), F.length);
-const AddressRange Et(Ft.end(), E.length);
-const AddressRange injected(Et.end(), 5);
-const AddressRange H1t(injected.end(), 4); // H is split.
-const AddressRange G1t(H1t.end(), G.length); // G is copied.
-const AddressRange G2t(G1t.end(), G.length); // G is copied.
-const AddressRange H2t(G2t.end(), 3); // H is split.
-
-class BuildImageMapTest : public testing::Test {
- public:
- static const DWORD kInvalidAddress = 0xFFFFFFFF;
-
- void InitOmapData() {
- omap_data.length_original = H.end();
-
- // Build the OMAPTO vector (from transformed to original).
- omap_data.omap_to.push_back(CreateOmap(Bt.rva, B.rva));
- omap_data.omap_to.push_back(CreateOmap(Dt.rva, D.rva));
- omap_data.omap_to.push_back(CreateOmap(Ft.rva, F.rva));
- omap_data.omap_to.push_back(CreateOmap(Et.rva, E.rva));
- omap_data.omap_to.push_back(CreateOmap(injected.rva, kInvalidAddress));
- omap_data.omap_to.push_back(CreateOmap(H1t.rva, H.rva));
- omap_data.omap_to.push_back(CreateOmap(G1t.rva, G.rva));
- omap_data.omap_to.push_back(CreateOmap(G2t.rva, G.rva));
- omap_data.omap_to.push_back(CreateOmap(H2t.rva, H.rva + H1t.length));
- omap_data.omap_to.push_back(CreateOmap(H2t.end(), kInvalidAddress));
-
- // Build the OMAPFROM vector (from original to transformed).
- omap_data.omap_from.push_back(CreateOmap(B.rva, Bt.rva));
- omap_data.omap_from.push_back(CreateOmap(C.rva, kInvalidAddress));
- omap_data.omap_from.push_back(CreateOmap(D.rva, Dt.rva));
- omap_data.omap_from.push_back(CreateOmap(E.rva, Et.rva));
- omap_data.omap_from.push_back(CreateOmap(F.rva, Ft.rva));
- omap_data.omap_from.push_back(CreateOmap(G.rva, G1t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.rva, H1t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.rva + H1t.length, H2t.rva));
- omap_data.omap_from.push_back(CreateOmap(H.end(), kInvalidAddress));
- }
-
- OmapData omap_data;
-};
-
-} // namespace
-
-TEST_F(BuildImageMapTest, EmptyImageMapOnEmptyOmapData) {
- ASSERT_EQ(0u, omap_data.omap_from.size());
- ASSERT_EQ(0u, omap_data.omap_to.size());
- ASSERT_EQ(0u, omap_data.length_original);
-
- ImageMap image_map;
- BuildImageMap(omap_data, &image_map);
- EXPECT_EQ(0u, image_map.mapping.size());
- EXPECT_EQ(0u, image_map.endpoint_index_map.size());
-}
-
-TEST_F(BuildImageMapTest, ImageMapIsCorrect) {
- InitOmapData();
- ASSERT_LE(0u, omap_data.omap_from.size());
- ASSERT_LE(0u, omap_data.omap_to.size());
- ASSERT_LE(0u, omap_data.length_original);
-
- ImageMap image_map;
- BuildImageMap(omap_data, &image_map);
- EXPECT_LE(9u, image_map.mapping.size());
- EXPECT_LE(9u, image_map.endpoint_index_map.size());
-
- Mapping mapping;
- mapping.push_back(CreateMappedRange(0, 0, B.rva, 0, 0));
- // C is removed, and it originally comes immediately after B.
- mapping.push_back(CreateMappedRange(B.rva, Bt.rva, B.length, 0, C.length));
- // D is shortened by a length of 5.
- mapping.push_back(CreateMappedRange(D.rva, Dt.rva, Dt.length, 0, 5));
- // The injected content comes immediately after E in the transformed image.
- mapping.push_back(CreateMappedRange(E.rva, Et.rva, E.length, injected.length,
- 0));
- mapping.push_back(CreateMappedRange(F.rva, Ft.rva, F.length, 0, 0));
- // G is copied so creates two entries.
- mapping.push_back(CreateMappedRange(G.rva, G1t.rva, G.length, 0, 0));
- mapping.push_back(CreateMappedRange(G.rva, G2t.rva, G.length, 0, 0));
- // H is split, so create two entries.
- mapping.push_back(CreateMappedRange(H.rva, H1t.rva, H1t.length, 0, 0));
- mapping.push_back(CreateMappedRange(H.rva + H1t.length, H2t.rva, H2t.length,
- 0, 0));
- EXPECT_THAT(mapping,
- testing::ContainerEq(image_map.mapping));
-
- EndpointIndexMap endpoint_index_map;
- endpoint_index_map.push_back(CreateEndpointIndex(0, 0));
- endpoint_index_map.push_back(CreateEndpointIndex(B.rva, 1));
- endpoint_index_map.push_back(CreateEndpointIndex(D.rva, 2));
- endpoint_index_map.push_back(CreateEndpointIndex(E.rva, 3));
- endpoint_index_map.push_back(CreateEndpointIndex(F.rva, 4));
- // G is duplicated so 2 ranges map back to it, hence the skip from 5 to 7.
- endpoint_index_map.push_back(CreateEndpointIndex(G.rva, 5));
- // H is split so we expect 2 endpoints to show up attributed to it.
- endpoint_index_map.push_back(CreateEndpointIndex(H.rva, 7));
- endpoint_index_map.push_back(CreateEndpointIndex(H.rva + H1t.length, 8));
- endpoint_index_map.push_back(CreateEndpointIndex(H.end(), 9));
- EXPECT_THAT(endpoint_index_map,
- testing::ContainerEq(image_map.endpoint_index_map));
-}
-
-namespace {
-
-class MapAddressRangeTest : public BuildImageMapTest {
- public:
- typedef BuildImageMapTest Super;
- virtual void SetUp() {
- Super::SetUp();
- InitOmapData();
- BuildImageMap(omap_data, &image_map);
- }
-
- ImageMap image_map;
-
- private:
- using BuildImageMapTest::InitOmapData;
- using BuildImageMapTest::omap_data;
-};
-
-} // namespace
-
-TEST_F(MapAddressRangeTest, EmptyImageMapReturnsIdentity) {
- ImageMap im;
- AddressRangeVector mapped_ranges;
- AddressRange ar(0, 1024);
- MapAddressRange(im, ar, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_EQ(ar, mapped_ranges[0]);
-}
-
-TEST_F(MapAddressRangeTest, MapOutOfImage) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(H.end() + 10, 10), &mapped_ranges);
- EXPECT_EQ(0u, mapped_ranges.size());
-}
-
-TEST_F(MapAddressRangeTest, MapIdentity) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, B, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(B));
-}
-
-TEST_F(MapAddressRangeTest, MapReorderedContiguous) {
- AddressRangeVector mapped_ranges;
-
- AddressRange DEF(D.rva, F.end() - D.rva);
- MapAddressRange(image_map, DEF, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange DFEt(Dt.rva, Et.end() - Dt.rva);
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(DFEt));
-}
-
-TEST_F(MapAddressRangeTest, MapEmptySingle) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(D.rva, 0), &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(Dt.rva, 0)));
-}
-
-TEST_F(MapAddressRangeTest, MapEmptyCopied) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, AddressRange(G.rva, 0), &mapped_ranges);
- EXPECT_EQ(2u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(G1t.rva, 0),
- AddressRange(G2t.rva, 0)));
-}
-
-TEST_F(MapAddressRangeTest, MapCopiedContiguous) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, G, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(
- AddressRange(G1t.rva, G2t.end() - G1t.rva)));
-}
-
-TEST_F(MapAddressRangeTest, MapSplitDiscontiguous) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, H, &mapped_ranges);
- EXPECT_EQ(2u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(H1t, H2t));
-}
-
-TEST_F(MapAddressRangeTest, MapInjected) {
- AddressRangeVector mapped_ranges;
-
- AddressRange EFGH(E.rva, H.end() - E.rva);
- MapAddressRange(image_map, EFGH, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange FEHGGHt(Ft.rva, H2t.end() - Ft.rva);
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(FEHGGHt));
-}
-
-TEST_F(MapAddressRangeTest, MapRemovedEntirely) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, C, &mapped_ranges);
- EXPECT_EQ(0u, mapped_ranges.size());
-}
-
-TEST_F(MapAddressRangeTest, MapRemovedPartly) {
- AddressRangeVector mapped_ranges;
- MapAddressRange(image_map, D, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(Dt));
-}
-
-TEST_F(MapAddressRangeTest, MapFull) {
- AddressRangeVector mapped_ranges;
-
- AddressRange AH(0, H.end());
- MapAddressRange(image_map, AH, &mapped_ranges);
- EXPECT_EQ(1u, mapped_ranges.size());
-
- AddressRange AHt(0, H2t.end());
- EXPECT_THAT(mapped_ranges, testing::ElementsAre(AHt));
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
deleted file mode 100644
index 01f4ce3b7..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.cc
+++ /dev/null
@@ -1,1369 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "common/windows/pdb_source_line_writer.h"
-
-#include <windows.h>
-#include <winnt.h>
-#include <atlbase.h>
-#include <dia2.h>
-#include <diacreate.h>
-#include <ImageHlp.h>
-#include <stdio.h>
-
-#include <limits>
-#include <set>
-
-#include "common/windows/dia_util.h"
-#include "common/windows/guid_string.h"
-#include "common/windows/string_utils-inl.h"
-
-// This constant may be missing from DbgHelp.h. See the documentation for
-// IDiaSymbol::get_undecoratedNameEx.
-#ifndef UNDNAME_NO_ECSU
-#define UNDNAME_NO_ECSU 0x8000 // Suppresses enum/class/struct/union.
-#endif // UNDNAME_NO_ECSU
-
-/*
- * Not defined in WinNT.h for some reason. Definitions taken from:
- * http://uninformed.org/index.cgi?v=4&a=1&p=13
- *
- */
-typedef unsigned char UBYTE;
-
-#if !defined(_WIN64)
-#define UNW_FLAG_EHANDLER 0x01
-#define UNW_FLAG_UHANDLER 0x02
-#define UNW_FLAG_CHAININFO 0x04
-#endif
-
-union UnwindCode {
- struct {
- UBYTE offset_in_prolog;
- UBYTE unwind_operation_code : 4;
- UBYTE operation_info : 4;
- };
- USHORT frame_offset;
-};
-
-enum UnwindOperationCodes {
- UWOP_PUSH_NONVOL = 0, /* info == register number */
- UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
- UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
- UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
- UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
- UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
- // XXX: these are missing from MSDN!
- // See: http://www.osronline.com/ddkx/kmarch/64bitamd_4rs7.htm
- UWOP_SAVE_XMM,
- UWOP_SAVE_XMM_FAR,
- UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
- UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
- UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
-};
-
-// See: http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
-// Note: some fields removed as we don't use them.
-struct UnwindInfo {
- UBYTE version : 3;
- UBYTE flags : 5;
- UBYTE size_of_prolog;
- UBYTE count_of_codes;
- UBYTE frame_register : 4;
- UBYTE frame_offset : 4;
- UnwindCode unwind_code[1];
-};
-
-namespace google_breakpad {
-
-namespace {
-
-using std::vector;
-
-// A helper class to scope a PLOADED_IMAGE.
-class AutoImage {
- public:
- explicit AutoImage(PLOADED_IMAGE img) : img_(img) {}
- ~AutoImage() {
- if (img_)
- ImageUnload(img_);
- }
-
- operator PLOADED_IMAGE() { return img_; }
- PLOADED_IMAGE operator->() { return img_; }
-
- private:
- PLOADED_IMAGE img_;
-};
-
-bool CreateDiaDataSourceInstance(CComPtr<IDiaDataSource> &data_source) {
- if (SUCCEEDED(data_source.CoCreateInstance(CLSID_DiaSource))) {
- return true;
- }
-
- class DECLSPEC_UUID("B86AE24D-BF2F-4ac9-B5A2-34B14E4CE11D") DiaSource100;
- class DECLSPEC_UUID("761D3BCD-1304-41D5-94E8-EAC54E4AC172") DiaSource110;
- class DECLSPEC_UUID("3BFCEA48-620F-4B6B-81F7-B9AF75454C7D") DiaSource120;
- class DECLSPEC_UUID("E6756135-1E65-4D17-8576-610761398C3C") DiaSource140;
-
- // If the CoCreateInstance call above failed, msdia*.dll is not registered.
- // We can try loading the DLL corresponding to the #included DIA SDK, but
- // the DIA headers don't provide a version. Lets try to figure out which DIA
- // version we're compiling against by comparing CLSIDs.
- const wchar_t *msdia_dll = nullptr;
- if (CLSID_DiaSource == _uuidof(DiaSource100)) {
- msdia_dll = L"msdia100.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource110)) {
- msdia_dll = L"msdia110.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource120)) {
- msdia_dll = L"msdia120.dll";
- } else if (CLSID_DiaSource == _uuidof(DiaSource140)) {
- msdia_dll = L"msdia140.dll";
- }
-
- if (msdia_dll &&
- SUCCEEDED(NoRegCoCreate(msdia_dll, CLSID_DiaSource, IID_IDiaDataSource,
- reinterpret_cast<void **>(&data_source)))) {
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
-PDBSourceLineWriter::PDBSourceLineWriter() : output_(NULL) {
-}
-
-PDBSourceLineWriter::~PDBSourceLineWriter() {
-}
-
-bool PDBSourceLineWriter::SetCodeFile(const wstring &exe_file) {
- if (code_file_.empty()) {
- code_file_ = exe_file;
- return true;
- }
- // Setting a different code file path is an error. It is success only if the
- // file paths are the same.
- return exe_file == code_file_;
-}
-
-bool PDBSourceLineWriter::Open(const wstring &file, FileFormat format) {
- Close();
- code_file_.clear();
-
- if (FAILED(CoInitialize(NULL))) {
- fprintf(stderr, "CoInitialize failed\n");
- return false;
- }
-
- CComPtr<IDiaDataSource> data_source;
- if (!CreateDiaDataSourceInstance(data_source)) {
- const int kGuidSize = 64;
- wchar_t classid[kGuidSize] = {0};
- StringFromGUID2(CLSID_DiaSource, classid, kGuidSize);
- fprintf(stderr, "CoCreateInstance CLSID_DiaSource %S failed "
- "(msdia*.dll unregistered?)\n", classid);
- return false;
- }
-
- switch (format) {
- case PDB_FILE:
- if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
- fprintf(stderr, "loadDataFromPdb failed for %ws\n", file.c_str());
- return false;
- }
- break;
- case EXE_FILE:
- if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
- fprintf(stderr, "loadDataForExe failed for %ws\n", file.c_str());
- return false;
- }
- code_file_ = file;
- break;
- case ANY_FILE:
- if (FAILED(data_source->loadDataFromPdb(file.c_str()))) {
- if (FAILED(data_source->loadDataForExe(file.c_str(), NULL, NULL))) {
- fprintf(stderr, "loadDataForPdb and loadDataFromExe failed for %ws\n",
- file.c_str());
- return false;
- }
- code_file_ = file;
- }
- break;
- default:
- fprintf(stderr, "Unknown file format\n");
- return false;
- }
-
- if (FAILED(data_source->openSession(&session_))) {
- fprintf(stderr, "openSession failed\n");
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintLines(IDiaEnumLineNumbers *lines) {
- // The line number format is:
- // <rva> <line number> <source file id>
- CComPtr<IDiaLineNumber> line;
- ULONG count;
-
- while (SUCCEEDED(lines->Next(1, &line, &count)) && count == 1) {
- DWORD rva;
- if (FAILED(line->get_relativeVirtualAddress(&rva))) {
- fprintf(stderr, "failed to get line rva\n");
- return false;
- }
-
- DWORD length;
- if (FAILED(line->get_length(&length))) {
- fprintf(stderr, "failed to get line code length\n");
- return false;
- }
-
- DWORD dia_source_id;
- if (FAILED(line->get_sourceFileId(&dia_source_id))) {
- fprintf(stderr, "failed to get line source file id\n");
- return false;
- }
- // duplicate file names are coalesced to share one ID
- DWORD source_id = GetRealFileID(dia_source_id);
-
- DWORD line_num;
- if (FAILED(line->get_lineNumber(&line_num))) {
- fprintf(stderr, "failed to get line number\n");
- return false;
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, length), &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "%x %x %d %d\n", ranges[i].rva, ranges[i].length,
- line_num, source_id);
- }
- line.Release();
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFunction(IDiaSymbol *function,
- IDiaSymbol *block) {
- // The function format is:
- // FUNC <address> <length> <param_stack_size> <function>
- DWORD rva;
- if (FAILED(block->get_relativeVirtualAddress(&rva))) {
- fprintf(stderr, "couldn't get rva\n");
- return false;
- }
-
- ULONGLONG length;
- if (FAILED(block->get_length(&length))) {
- fprintf(stderr, "failed to get function length\n");
- return false;
- }
-
- if (length == 0) {
- // Silently ignore zero-length functions, which can infrequently pop up.
- return true;
- }
-
- CComBSTR name;
- int stack_param_size;
- if (!GetSymbolFunctionName(function, &name, &stack_param_size)) {
- return false;
- }
-
- // If the decorated name didn't give the parameter size, try to
- // calculate it.
- if (stack_param_size < 0) {
- stack_param_size = GetFunctionStackParamSize(function);
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, static_cast<DWORD>(length)),
- &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "FUNC %x %x %x %ws\n",
- ranges[i].rva, ranges[i].length, stack_param_size,
- name.m_str);
- }
-
- CComPtr<IDiaEnumLineNumbers> lines;
- if (FAILED(session_->findLinesByRVA(rva, DWORD(length), &lines))) {
- return false;
- }
-
- if (!PrintLines(lines)) {
- return false;
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintSourceFiles() {
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumSymbols> compilands;
- if (FAILED(global->findChildren(SymTagCompiland, NULL,
- nsNone, &compilands))) {
- fprintf(stderr, "findChildren failed\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> compiland;
- ULONG count;
- while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
- CComPtr<IDiaEnumSourceFiles> source_files;
- if (FAILED(session_->findFile(compiland, NULL, nsNone, &source_files))) {
- return false;
- }
- CComPtr<IDiaSourceFile> file;
- while (SUCCEEDED(source_files->Next(1, &file, &count)) && count == 1) {
- DWORD file_id;
- if (FAILED(file->get_uniqueId(&file_id))) {
- return false;
- }
-
- CComBSTR file_name;
- if (FAILED(file->get_fileName(&file_name))) {
- return false;
- }
-
- wstring file_name_string(file_name);
- if (!FileIDIsCached(file_name_string)) {
- // this is a new file name, cache it and output a FILE line.
- CacheFileID(file_name_string, file_id);
- fwprintf(output_, L"FILE %d %ws\n", file_id, file_name_string.c_str());
- } else {
- // this file name has already been seen, just save this
- // ID for later lookup.
- StoreDuplicateFileID(file_name_string, file_id);
- }
- file.Release();
- }
- compiland.Release();
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFunctions() {
- ULONG count = 0;
- DWORD rva = 0;
- CComPtr<IDiaSymbol> global;
- HRESULT hr;
-
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComPtr<IDiaEnumSymbols> symbols = NULL;
-
- // Find all function symbols first.
- std::set<DWORD> rvas;
- hr = global->findChildren(SymTagFunction, NULL, nsNone, &symbols);
-
- if (SUCCEEDED(hr)) {
- CComPtr<IDiaSymbol> symbol = NULL;
-
- while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
- if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
- // To maintain existing behavior of one symbol per address, place the
- // rva onto a set here to uniquify them.
- rvas.insert(rva);
- } else {
- fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
- return false;
- }
-
- symbol.Release();
- }
-
- symbols.Release();
- }
-
- // Find all public symbols. Store public symbols that are not also private
- // symbols for later.
- std::set<DWORD> public_only_rvas;
- hr = global->findChildren(SymTagPublicSymbol, NULL, nsNone, &symbols);
-
- if (SUCCEEDED(hr)) {
- CComPtr<IDiaSymbol> symbol = NULL;
-
- while (SUCCEEDED(symbols->Next(1, &symbol, &count)) && count == 1) {
- if (SUCCEEDED(symbol->get_relativeVirtualAddress(&rva))) {
- if (rvas.count(rva) == 0) {
- rvas.insert(rva); // Keep symbols in rva order.
- public_only_rvas.insert(rva);
- }
- } else {
- fprintf(stderr, "get_relativeVirtualAddress failed on the symbol\n");
- return false;
- }
-
- symbol.Release();
- }
-
- symbols.Release();
- }
-
- std::set<DWORD>::iterator it;
-
- // For each rva, dump the first symbol DIA knows about at the address.
- for (it = rvas.begin(); it != rvas.end(); ++it) {
- CComPtr<IDiaSymbol> symbol = NULL;
- // If the symbol is not in the public list, look for SymTagFunction. This is
- // a workaround to a bug where DIA will hang if searching for a private
- // symbol at an address where only a public symbol exists.
- // See http://connect.microsoft.com/VisualStudio/feedback/details/722366
- if (public_only_rvas.count(*it) == 0) {
- if (SUCCEEDED(session_->findSymbolByRVA(*it, SymTagFunction, &symbol))) {
- // Sometimes findSymbolByRVA returns S_OK, but NULL.
- if (symbol) {
- if (!PrintFunction(symbol, symbol))
- return false;
- symbol.Release();
- }
- } else {
- fprintf(stderr, "findSymbolByRVA SymTagFunction failed\n");
- return false;
- }
- } else if (SUCCEEDED(session_->findSymbolByRVA(*it,
- SymTagPublicSymbol,
- &symbol))) {
- // Sometimes findSymbolByRVA returns S_OK, but NULL.
- if (symbol) {
- if (!PrintCodePublicSymbol(symbol))
- return false;
- symbol.Release();
- }
- } else {
- fprintf(stderr, "findSymbolByRVA SymTagPublicSymbol failed\n");
- return false;
- }
- }
-
- // When building with PGO, the compiler can split functions into
- // "hot" and "cold" blocks, and move the "cold" blocks out to separate
- // pages, so the function can be noncontiguous. To find these blocks,
- // we have to iterate over all the compilands, and then find blocks
- // that are children of them. We can then find the lexical parents
- // of those blocks and print out an extra FUNC line for blocks
- // that are not contained in their parent functions.
- CComPtr<IDiaEnumSymbols> compilands;
- if (FAILED(global->findChildren(SymTagCompiland, NULL,
- nsNone, &compilands))) {
- fprintf(stderr, "findChildren failed on the global\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> compiland;
- while (SUCCEEDED(compilands->Next(1, &compiland, &count)) && count == 1) {
- CComPtr<IDiaEnumSymbols> blocks;
- if (FAILED(compiland->findChildren(SymTagBlock, NULL,
- nsNone, &blocks))) {
- fprintf(stderr, "findChildren failed on a compiland\n");
- return false;
- }
-
- CComPtr<IDiaSymbol> block;
- while (SUCCEEDED(blocks->Next(1, &block, &count)) && count == 1) {
- // find this block's lexical parent function
- CComPtr<IDiaSymbol> parent;
- DWORD tag;
- if (SUCCEEDED(block->get_lexicalParent(&parent)) &&
- SUCCEEDED(parent->get_symTag(&tag)) &&
- tag == SymTagFunction) {
- // now get the block's offset and the function's offset and size,
- // and determine if the block is outside of the function
- DWORD func_rva, block_rva;
- ULONGLONG func_length;
- if (SUCCEEDED(block->get_relativeVirtualAddress(&block_rva)) &&
- SUCCEEDED(parent->get_relativeVirtualAddress(&func_rva)) &&
- SUCCEEDED(parent->get_length(&func_length))) {
- if (block_rva < func_rva || block_rva > (func_rva + func_length)) {
- if (!PrintFunction(parent, block)) {
- return false;
- }
- }
- }
- }
- parent.Release();
- block.Release();
- }
- blocks.Release();
- compiland.Release();
- }
-
- global.Release();
- return true;
-}
-
-#undef max
-
-bool PDBSourceLineWriter::PrintFrameDataUsingPDB() {
- // It would be nice if it were possible to output frame data alongside the
- // associated function, as is done with line numbers, but the DIA API
- // doesn't make it possible to get the frame data in that way.
-
- CComPtr<IDiaEnumFrameData> frame_data_enum;
- if (!FindTable(session_, &frame_data_enum))
- return false;
-
- DWORD last_type = std::numeric_limits<DWORD>::max();
- DWORD last_rva = std::numeric_limits<DWORD>::max();
- DWORD last_code_size = 0;
- DWORD last_prolog_size = std::numeric_limits<DWORD>::max();
-
- CComPtr<IDiaFrameData> frame_data;
- ULONG count = 0;
- while (SUCCEEDED(frame_data_enum->Next(1, &frame_data, &count)) &&
- count == 1) {
- DWORD type;
- if (FAILED(frame_data->get_type(&type)))
- return false;
-
- DWORD rva;
- if (FAILED(frame_data->get_relativeVirtualAddress(&rva)))
- return false;
-
- DWORD code_size;
- if (FAILED(frame_data->get_lengthBlock(&code_size)))
- return false;
-
- DWORD prolog_size;
- if (FAILED(frame_data->get_lengthProlog(&prolog_size)))
- return false;
-
- // parameter_size is the size of parameters passed on the stack. If any
- // parameters are not passed on the stack (such as in registers), their
- // sizes will not be included in parameter_size.
- DWORD parameter_size;
- if (FAILED(frame_data->get_lengthParams(&parameter_size)))
- return false;
-
- DWORD saved_register_size;
- if (FAILED(frame_data->get_lengthSavedRegisters(&saved_register_size)))
- return false;
-
- DWORD local_size;
- if (FAILED(frame_data->get_lengthLocals(&local_size)))
- return false;
-
- // get_maxStack can return S_FALSE, just use 0 in that case.
- DWORD max_stack_size = 0;
- if (FAILED(frame_data->get_maxStack(&max_stack_size)))
- return false;
-
- // get_programString can return S_FALSE, indicating that there is no
- // program string. In that case, check whether %ebp is used.
- HRESULT program_string_result;
- CComBSTR program_string;
- if (FAILED(program_string_result = frame_data->get_program(
- &program_string))) {
- return false;
- }
-
- // get_allocatesBasePointer can return S_FALSE, treat that as though
- // %ebp is not used.
- BOOL allocates_base_pointer = FALSE;
- if (program_string_result != S_OK) {
- if (FAILED(frame_data->get_allocatesBasePointer(
- &allocates_base_pointer))) {
- return false;
- }
- }
-
- // Only print out a line if type, rva, code_size, or prolog_size have
- // changed from the last line. It is surprisingly common (especially in
- // system library PDBs) for DIA to return a series of identical
- // IDiaFrameData objects. For kernel32.pdb from Windows XP SP2 on x86,
- // this check reduces the size of the dumped symbol file by a third.
- if (type != last_type || rva != last_rva || code_size != last_code_size ||
- prolog_size != last_prolog_size) {
- // The prolog and the code portions of the frame have to be treated
- // independently as they may have independently changed in size, or may
- // even have been split.
- // NOTE: If epilog size is ever non-zero, we have to do something
- // similar with it.
-
- // Figure out where the prolog bytes have landed.
- AddressRangeVector prolog_ranges;
- if (prolog_size > 0) {
- MapAddressRange(image_map_, AddressRange(rva, prolog_size),
- &prolog_ranges);
- }
-
- // And figure out where the code bytes have landed.
- AddressRangeVector code_ranges;
- MapAddressRange(image_map_,
- AddressRange(rva + prolog_size,
- code_size - prolog_size),
- &code_ranges);
-
- struct FrameInfo {
- DWORD rva;
- DWORD code_size;
- DWORD prolog_size;
- };
- std::vector<FrameInfo> frame_infos;
-
- // Special case: The prolog and the code bytes remain contiguous. This is
- // only done for compactness of the symbol file, and we could actually
- // be outputting independent frame info for the prolog and code portions.
- if (prolog_ranges.size() == 1 && code_ranges.size() == 1 &&
- prolog_ranges[0].end() == code_ranges[0].rva) {
- FrameInfo fi = { prolog_ranges[0].rva,
- prolog_ranges[0].length + code_ranges[0].length,
- prolog_ranges[0].length };
- frame_infos.push_back(fi);
- } else {
- // Otherwise we output the prolog and code frame info independently.
- for (size_t i = 0; i < prolog_ranges.size(); ++i) {
- FrameInfo fi = { prolog_ranges[i].rva,
- prolog_ranges[i].length,
- prolog_ranges[i].length };
- frame_infos.push_back(fi);
- }
- for (size_t i = 0; i < code_ranges.size(); ++i) {
- FrameInfo fi = { code_ranges[i].rva, code_ranges[i].length, 0 };
- frame_infos.push_back(fi);
- }
- }
-
- for (size_t i = 0; i < frame_infos.size(); ++i) {
- const FrameInfo& fi(frame_infos[i]);
- fprintf(output_, "STACK WIN %x %x %x %x %x %x %x %x %x %d ",
- type, fi.rva, fi.code_size, fi.prolog_size,
- 0 /* epilog_size */, parameter_size, saved_register_size,
- local_size, max_stack_size, program_string_result == S_OK);
- if (program_string_result == S_OK) {
- fprintf(output_, "%ws\n", program_string.m_str);
- } else {
- fprintf(output_, "%d\n", allocates_base_pointer);
- }
- }
-
- last_type = type;
- last_rva = rva;
- last_code_size = code_size;
- last_prolog_size = prolog_size;
- }
-
- frame_data.Release();
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFrameDataUsingEXE() {
- if (code_file_.empty() && !FindPEFile()) {
- fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
- return false;
- }
-
- // Convert wchar to native charset because ImageLoad only takes
- // a PSTR as input.
- string code_file;
- if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
- return false;
- }
-
- AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
- if (!img) {
- fprintf(stderr, "Failed to load %s\n", code_file.c_str());
- return false;
- }
- PIMAGE_OPTIONAL_HEADER64 optional_header =
- &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
- if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- fprintf(stderr, "Not a PE32+ image\n");
- return false;
- }
-
- // Read Exception Directory
- DWORD exception_rva = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
- DWORD exception_size = optional_header->
- DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
- PIMAGE_RUNTIME_FUNCTION_ENTRY funcs =
- static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- exception_rva,
- &img->LastRvaSection));
- for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
- DWORD unwind_rva = funcs[i].UnwindInfoAddress;
- // handle chaining
- while (unwind_rva & 0x1) {
- unwind_rva ^= 0x1;
- PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
- static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
- unwind_rva = chained_func->UnwindInfoAddress;
- }
-
- UnwindInfo *unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- unwind_rva,
- &img->LastRvaSection));
-
- DWORD stack_size = 8; // minimal stack size is 8 for RIP
- DWORD rip_offset = 8;
- do {
- for (UBYTE c = 0; c < unwind_info->count_of_codes; c++) {
- UnwindCode *unwind_code = &unwind_info->unwind_code[c];
- switch (unwind_code->unwind_operation_code) {
- case UWOP_PUSH_NONVOL: {
- stack_size += 8;
- break;
- }
- case UWOP_ALLOC_LARGE: {
- if (unwind_code->operation_info == 0) {
- c++;
- if (c < unwind_info->count_of_codes)
- stack_size += (unwind_code + 1)->frame_offset * 8;
- } else {
- c += 2;
- if (c < unwind_info->count_of_codes)
- stack_size += (unwind_code + 1)->frame_offset |
- ((unwind_code + 2)->frame_offset << 16);
- }
- break;
- }
- case UWOP_ALLOC_SMALL: {
- stack_size += unwind_code->operation_info * 8 + 8;
- break;
- }
- case UWOP_SET_FPREG:
- case UWOP_SAVE_XMM:
- case UWOP_SAVE_XMM_FAR:
- break;
- case UWOP_SAVE_NONVOL:
- case UWOP_SAVE_XMM128: {
- c++; // skip slot with offset
- break;
- }
- case UWOP_SAVE_NONVOL_FAR:
- case UWOP_SAVE_XMM128_FAR: {
- c += 2; // skip 2 slots with offset
- break;
- }
- case UWOP_PUSH_MACHFRAME: {
- if (unwind_code->operation_info) {
- stack_size += 88;
- } else {
- stack_size += 80;
- }
- rip_offset += 80;
- break;
- }
- }
- }
- if (unwind_info->flags & UNW_FLAG_CHAININFO) {
- PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
- reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
- (unwind_info->unwind_code +
- ((unwind_info->count_of_codes + 1) & ~1)));
-
- unwind_info = static_cast<UnwindInfo *>(
- ImageRvaToVa(img->FileHeader,
- img->MappedAddress,
- chained_func->UnwindInfoAddress,
- &img->LastRvaSection));
- } else {
- unwind_info = NULL;
- }
- } while (unwind_info);
- fprintf(output_, "STACK CFI INIT %x %x .cfa: $rsp .ra: .cfa %d - ^\n",
- funcs[i].BeginAddress,
- funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
- fprintf(output_, "STACK CFI %x .cfa: $rsp %d +\n",
- funcs[i].BeginAddress, stack_size);
- }
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintFrameData() {
- PDBModuleInfo info;
- if (GetModuleInfo(&info) && info.cpu == L"x86_64") {
- return PrintFrameDataUsingEXE();
- } else {
- return PrintFrameDataUsingPDB();
- }
- return false;
-}
-
-bool PDBSourceLineWriter::PrintCodePublicSymbol(IDiaSymbol *symbol) {
- BOOL is_code;
- if (FAILED(symbol->get_code(&is_code))) {
- return false;
- }
- if (!is_code) {
- return true;
- }
-
- DWORD rva;
- if (FAILED(symbol->get_relativeVirtualAddress(&rva))) {
- return false;
- }
-
- CComBSTR name;
- int stack_param_size;
- if (!GetSymbolFunctionName(symbol, &name, &stack_param_size)) {
- return false;
- }
-
- AddressRangeVector ranges;
- MapAddressRange(image_map_, AddressRange(rva, 1), &ranges);
- for (size_t i = 0; i < ranges.size(); ++i) {
- fprintf(output_, "PUBLIC %x %x %ws\n", ranges[i].rva,
- stack_param_size > 0 ? stack_param_size : 0,
- name.m_str);
- }
- return true;
-}
-
-bool PDBSourceLineWriter::PrintPDBInfo() {
- PDBModuleInfo info;
- if (!GetModuleInfo(&info)) {
- return false;
- }
-
- // Hard-code "windows" for the OS because that's the only thing that makes
- // sense for PDB files. (This might not be strictly correct for Windows CE
- // support, but we don't care about that at the moment.)
- fprintf(output_, "MODULE windows %ws %ws %ws\n",
- info.cpu.c_str(), info.debug_identifier.c_str(),
- info.debug_file.c_str());
-
- return true;
-}
-
-bool PDBSourceLineWriter::PrintPEInfo() {
- PEModuleInfo info;
- if (!GetPEInfo(&info)) {
- return false;
- }
-
- fprintf(output_, "INFO CODE_ID %ws %ws\n",
- info.code_identifier.c_str(),
- info.code_file.c_str());
- return true;
-}
-
-// wcstol_positive_strict is sort of like wcstol, but much stricter. string
-// should be a buffer pointing to a null-terminated string containing only
-// decimal digits. If the entire string can be converted to an integer
-// without overflowing, and there are no non-digit characters before the
-// result is set to the value and this function returns true. Otherwise,
-// this function returns false. This is an alternative to the strtol, atoi,
-// and scanf families, which are not as strict about input and in some cases
-// don't provide a good way for the caller to determine if a conversion was
-// successful.
-static bool wcstol_positive_strict(wchar_t *string, int *result) {
- int value = 0;
- for (wchar_t *c = string; *c != '\0'; ++c) {
- int last_value = value;
- value *= 10;
- // Detect overflow.
- if (value / 10 != last_value || value < 0) {
- return false;
- }
- if (*c < '0' || *c > '9') {
- return false;
- }
- unsigned int c_value = *c - '0';
- last_value = value;
- value += c_value;
- // Detect overflow.
- if (value < last_value) {
- return false;
- }
- // Forbid leading zeroes unless the string is just "0".
- if (value == 0 && *(c+1) != '\0') {
- return false;
- }
- }
- *result = value;
- return true;
-}
-
-bool PDBSourceLineWriter::FindPEFile() {
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- fprintf(stderr, "get_globalScope failed\n");
- return false;
- }
-
- CComBSTR symbols_file;
- if (SUCCEEDED(global->get_symbolsFileName(&symbols_file))) {
- wstring file(symbols_file);
-
- // Look for an EXE or DLL file.
- const wchar_t *extensions[] = { L"exe", L"dll" };
- for (int i = 0; i < sizeof(extensions) / sizeof(extensions[0]); i++) {
- size_t dot_pos = file.find_last_of(L".");
- if (dot_pos != wstring::npos) {
- file.replace(dot_pos + 1, wstring::npos, extensions[i]);
- // Check if this file exists.
- if (GetFileAttributesW(file.c_str()) != INVALID_FILE_ATTRIBUTES) {
- code_file_ = file;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-// static
-bool PDBSourceLineWriter::GetSymbolFunctionName(IDiaSymbol *function,
- BSTR *name,
- int *stack_param_size) {
- *stack_param_size = -1;
- const DWORD undecorate_options = UNDNAME_NO_MS_KEYWORDS |
- UNDNAME_NO_FUNCTION_RETURNS |
- UNDNAME_NO_ALLOCATION_MODEL |
- UNDNAME_NO_ALLOCATION_LANGUAGE |
- UNDNAME_NO_THISTYPE |
- UNDNAME_NO_ACCESS_SPECIFIERS |
- UNDNAME_NO_THROW_SIGNATURES |
- UNDNAME_NO_MEMBER_TYPE |
- UNDNAME_NO_RETURN_UDT_MODEL |
- UNDNAME_NO_ECSU;
-
- // Use get_undecoratedNameEx to get readable C++ names with arguments.
- if (function->get_undecoratedNameEx(undecorate_options, name) != S_OK) {
- if (function->get_name(name) != S_OK) {
- fprintf(stderr, "failed to get function name\n");
- return false;
- }
-
- // It's possible for get_name to return an empty string, so
- // special-case that.
- if (wcscmp(*name, L"") == 0) {
- SysFreeString(*name);
- // dwarf_cu_to_module.cc uses "<name omitted>", so match that.
- *name = SysAllocString(L"<name omitted>");
- return true;
- }
-
- // If a name comes from get_name because no undecorated form existed,
- // it's already formatted properly to be used as output. Don't do any
- // additional processing.
- //
- // MSVC7's DIA seems to not undecorate names in as many cases as MSVC8's.
- // This will result in calling get_name for some C++ symbols, so
- // all of the parameter and return type information may not be included in
- // the name string.
- } else {
- // C++ uses a bogus "void" argument for functions and methods that don't
- // take any parameters. Take it out of the undecorated name because it's
- // ugly and unnecessary.
- const wchar_t *replace_string = L"(void)";
- const size_t replace_length = wcslen(replace_string);
- const wchar_t *replacement_string = L"()";
- size_t length = wcslen(*name);
- if (length >= replace_length) {
- wchar_t *name_end = *name + length - replace_length;
- if (wcscmp(name_end, replace_string) == 0) {
- WindowsStringUtils::safe_wcscpy(name_end, replace_length,
- replacement_string);
- length = wcslen(*name);
- }
- }
-
- // Undecorate names used for stdcall and fastcall. These names prefix
- // the identifier with '_' (stdcall) or '@' (fastcall) and suffix it
- // with '@' followed by the number of bytes of parameters, in decimal.
- // If such a name is found, take note of the size and undecorate it.
- // Only do this for names that aren't C++, which is determined based on
- // whether the undecorated name contains any ':' or '(' characters.
- if (!wcschr(*name, ':') && !wcschr(*name, '(') &&
- (*name[0] == '_' || *name[0] == '@')) {
- wchar_t *last_at = wcsrchr(*name + 1, '@');
- if (last_at && wcstol_positive_strict(last_at + 1, stack_param_size)) {
- // If this function adheres to the fastcall convention, it accepts up
- // to the first 8 bytes of parameters in registers (%ecx and %edx).
- // We're only interested in the stack space used for parameters, so
- // so subtract 8 and don't let the size go below 0.
- if (*name[0] == '@') {
- if (*stack_param_size > 8) {
- *stack_param_size -= 8;
- } else {
- *stack_param_size = 0;
- }
- }
-
- // Undecorate the name by moving it one character to the left in its
- // buffer, and terminating it where the last '@' had been.
- WindowsStringUtils::safe_wcsncpy(*name, length,
- *name + 1, last_at - *name - 1);
- } else if (*name[0] == '_') {
- // This symbol's name is encoded according to the cdecl rules. The
- // name doesn't end in a '@' character followed by a decimal positive
- // integer, so it's not a stdcall name. Strip off the leading
- // underscore.
- WindowsStringUtils::safe_wcsncpy(*name, length, *name + 1, length);
- }
- }
- }
-
- return true;
-}
-
-// static
-int PDBSourceLineWriter::GetFunctionStackParamSize(IDiaSymbol *function) {
- // This implementation is highly x86-specific.
-
- // Gather the symbols corresponding to data.
- CComPtr<IDiaEnumSymbols> data_children;
- if (FAILED(function->findChildren(SymTagData, NULL, nsNone,
- &data_children))) {
- return 0;
- }
-
- // lowest_base is the lowest %ebp-relative byte offset used for a parameter.
- // highest_end is one greater than the highest offset (i.e. base + length).
- // Stack parameters are assumed to be contiguous, because in reality, they
- // are.
- int lowest_base = INT_MAX;
- int highest_end = INT_MIN;
-
- CComPtr<IDiaSymbol> child;
- DWORD count;
- while (SUCCEEDED(data_children->Next(1, &child, &count)) && count == 1) {
- // If any operation fails at this point, just proceed to the next child.
- // Use the next_child label instead of continue because child needs to
- // be released before it's reused. Declare constructable/destructable
- // types early to avoid gotos that cross initializations.
- CComPtr<IDiaSymbol> child_type;
-
- // DataIsObjectPtr is only used for |this|. Because |this| can be passed
- // as a stack parameter, look for it in addition to traditional
- // parameters.
- DWORD child_kind;
- if (FAILED(child->get_dataKind(&child_kind)) ||
- (child_kind != DataIsParam && child_kind != DataIsObjectPtr)) {
- goto next_child;
- }
-
- // Only concentrate on register-relative parameters. Parameters may also
- // be enregistered (passed directly in a register), but those don't
- // consume any stack space, so they're not of interest.
- DWORD child_location_type;
- if (FAILED(child->get_locationType(&child_location_type)) ||
- child_location_type != LocIsRegRel) {
- goto next_child;
- }
-
- // Of register-relative parameters, the only ones that make any sense are
- // %ebp- or %esp-relative. Note that MSVC's debugging information always
- // gives parameters as %ebp-relative even when a function doesn't use a
- // traditional frame pointer and stack parameters are accessed relative to
- // %esp, so just look for %ebp-relative parameters. If you wanted to
- // access parameters, you'd probably want to treat these %ebp-relative
- // offsets as if they were relative to %esp before a function's prolog
- // executed.
- DWORD child_register;
- if (FAILED(child->get_registerId(&child_register)) ||
- child_register != CV_REG_EBP) {
- goto next_child;
- }
-
- LONG child_register_offset;
- if (FAILED(child->get_offset(&child_register_offset))) {
- goto next_child;
- }
-
- // IDiaSymbol::get_type can succeed but still pass back a NULL value.
- if (FAILED(child->get_type(&child_type)) || !child_type) {
- goto next_child;
- }
-
- ULONGLONG child_length;
- if (FAILED(child_type->get_length(&child_length))) {
- goto next_child;
- }
-
- int child_end = child_register_offset + static_cast<ULONG>(child_length);
- if (child_register_offset < lowest_base) {
- lowest_base = child_register_offset;
- }
- if (child_end > highest_end) {
- highest_end = child_end;
- }
-
-next_child:
- child.Release();
- }
-
- int param_size = 0;
- // Make sure lowest_base isn't less than 4, because [%esp+4] is the lowest
- // possible address to find a stack parameter before executing a function's
- // prolog (see above). Some optimizations cause parameter offsets to be
- // lower than 4, but we're not concerned with those because we're only
- // looking for parameters contained in addresses higher than where the
- // return address is stored.
- if (lowest_base < 4) {
- lowest_base = 4;
- }
- if (highest_end > lowest_base) {
- // All stack parameters are pushed as at least 4-byte quantities. If the
- // last type was narrower than 4 bytes, promote it. This assumes that all
- // parameters' offsets are 4-byte-aligned, which is always the case. Only
- // worry about the last type, because we're not summing the type sizes,
- // just looking at the lowest and highest offsets.
- int remainder = highest_end % 4;
- if (remainder) {
- highest_end += 4 - remainder;
- }
-
- param_size = highest_end - lowest_base;
- }
-
- return param_size;
-}
-
-bool PDBSourceLineWriter::WriteMap(FILE *map_file) {
- output_ = map_file;
-
- // Load the OMAP information, and disable auto-translation of addresses in
- // preference of doing it ourselves.
- OmapData omap_data;
- if (!GetOmapDataAndDisableTranslation(session_, &omap_data))
- return false;
- BuildImageMap(omap_data, &image_map_);
-
- bool ret = PrintPDBInfo();
- // This is not a critical piece of the symbol file.
- PrintPEInfo();
- ret = ret &&
- PrintSourceFiles() &&
- PrintFunctions() &&
- PrintFrameData();
-
- output_ = NULL;
- return ret;
-}
-
-void PDBSourceLineWriter::Close() {
- session_.Release();
-}
-
-bool PDBSourceLineWriter::GetModuleInfo(PDBModuleInfo *info) {
- if (!info) {
- return false;
- }
-
- info->debug_file.clear();
- info->debug_identifier.clear();
- info->cpu.clear();
-
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global))) {
- return false;
- }
-
- DWORD machine_type;
- // get_machineType can return S_FALSE.
- if (global->get_machineType(&machine_type) == S_OK) {
- // The documentation claims that get_machineType returns a value from
- // the CV_CPU_TYPE_e enumeration, but that's not the case.
- // Instead, it returns one of the IMAGE_FILE_MACHINE values as
- // defined here:
- // http://msdn.microsoft.com/en-us/library/ms680313%28VS.85%29.aspx
- switch (machine_type) {
- case IMAGE_FILE_MACHINE_I386:
- info->cpu = L"x86";
- break;
- case IMAGE_FILE_MACHINE_AMD64:
- info->cpu = L"x86_64";
- break;
- default:
- info->cpu = L"unknown";
- break;
- }
- } else {
- // Unexpected, but handle gracefully.
- info->cpu = L"unknown";
- }
-
- // DWORD* and int* are not compatible. This is clean and avoids a cast.
- DWORD age;
- if (FAILED(global->get_age(&age))) {
- return false;
- }
-
- bool uses_guid;
- if (!UsesGUID(&uses_guid)) {
- return false;
- }
-
- if (uses_guid) {
- GUID guid;
- if (FAILED(global->get_guid(&guid))) {
- return false;
- }
-
- // Use the same format that the MS symbol server uses in filesystem
- // hierarchies.
- wchar_t age_string[9];
- swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]),
- L"%x", age);
-
- // remove when VC++7.1 is no longer supported
- age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0';
-
- info->debug_identifier = GUIDString::GUIDToSymbolServerWString(&guid);
- info->debug_identifier.append(age_string);
- } else {
- DWORD signature;
- if (FAILED(global->get_signature(&signature))) {
- return false;
- }
-
- // Use the same format that the MS symbol server uses in filesystem
- // hierarchies.
- wchar_t identifier_string[17];
- swprintf(identifier_string,
- sizeof(identifier_string) / sizeof(identifier_string[0]),
- L"%08X%x", signature, age);
-
- // remove when VC++7.1 is no longer supported
- identifier_string[sizeof(identifier_string) /
- sizeof(identifier_string[0]) - 1] = L'\0';
-
- info->debug_identifier = identifier_string;
- }
-
- CComBSTR debug_file_string;
- if (FAILED(global->get_symbolsFileName(&debug_file_string))) {
- return false;
- }
- info->debug_file =
- WindowsStringUtils::GetBaseName(wstring(debug_file_string));
-
- return true;
-}
-
-bool PDBSourceLineWriter::GetPEInfo(PEModuleInfo *info) {
- if (!info) {
- return false;
- }
-
- if (code_file_.empty() && !FindPEFile()) {
- fprintf(stderr, "Couldn't locate EXE or DLL file.\n");
- return false;
- }
-
- // Convert wchar to native charset because ImageLoad only takes
- // a PSTR as input.
- string code_file;
- if (!WindowsStringUtils::safe_wcstombs(code_file_, &code_file)) {
- return false;
- }
-
- AutoImage img(ImageLoad((PSTR)code_file.c_str(), NULL));
- if (!img) {
- fprintf(stderr, "Failed to open PE file: %s\n", code_file.c_str());
- return false;
- }
-
- info->code_file = WindowsStringUtils::GetBaseName(code_file_);
-
- // The date and time that the file was created by the linker.
- DWORD TimeDateStamp = img->FileHeader->FileHeader.TimeDateStamp;
- // The size of the file in bytes, including all headers.
- DWORD SizeOfImage = 0;
- PIMAGE_OPTIONAL_HEADER64 opt =
- &((PIMAGE_NT_HEADERS64)img->FileHeader)->OptionalHeader;
- if (opt->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
- // 64-bit PE file.
- SizeOfImage = opt->SizeOfImage;
- } else {
- // 32-bit PE file.
- SizeOfImage = img->FileHeader->OptionalHeader.SizeOfImage;
- }
- wchar_t code_identifier[32];
- swprintf(code_identifier,
- sizeof(code_identifier) / sizeof(code_identifier[0]),
- L"%08X%X", TimeDateStamp, SizeOfImage);
- info->code_identifier = code_identifier;
-
- return true;
-}
-
-bool PDBSourceLineWriter::UsesGUID(bool *uses_guid) {
- if (!uses_guid)
- return false;
-
- CComPtr<IDiaSymbol> global;
- if (FAILED(session_->get_globalScope(&global)))
- return false;
-
- GUID guid;
- if (FAILED(global->get_guid(&guid)))
- return false;
-
- DWORD signature;
- if (FAILED(global->get_signature(&signature)))
- return false;
-
- // There are two possibilities for guid: either it's a real 128-bit GUID
- // as identified in a code module by a new-style CodeView record, or it's
- // a 32-bit signature (timestamp) as identified by an old-style record.
- // See MDCVInfoPDB70 and MDCVInfoPDB20 in minidump_format.h.
- //
- // Because DIA doesn't provide a way to directly determine whether a module
- // uses a GUID or a 32-bit signature, this code checks whether the first 32
- // bits of guid are the same as the signature, and if the rest of guid is
- // zero. If so, then with a pretty high degree of certainty, there's an
- // old-style CodeView record in use. This method will only falsely find an
- // an old-style CodeView record if a real 128-bit GUID has its first 32
- // bits set the same as the module's signature (timestamp) and the rest of
- // the GUID is set to 0. This is highly unlikely.
-
- GUID signature_guid = {signature}; // 0-initializes other members
- *uses_guid = !IsEqualGUID(guid, signature_guid);
- return true;
-}
-
-} // namespace google_breakpad
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h b/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
deleted file mode 100644
index e9e89bb27..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/pdb_source_line_writer.h
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// PDBSourceLineWriter uses a pdb file produced by Visual C++ to output
-// a line/address map for use with BasicSourceLineResolver.
-
-#ifndef COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
-#define COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
-
-#include <atlcomcli.h>
-
-#include <unordered_map>
-#include <string>
-
-#include "common/windows/omap.h"
-
-struct IDiaEnumLineNumbers;
-struct IDiaSession;
-struct IDiaSymbol;
-
-namespace google_breakpad {
-
-using std::wstring;
-using std::unordered_map;
-
-// A structure that carries information that identifies a pdb file.
-struct PDBModuleInfo {
- public:
- // The basename of the pdb file from which information was loaded.
- wstring debug_file;
-
- // The pdb's identifier. For recent pdb files, the identifier consists
- // of the pdb's guid, in uppercase hexadecimal form without any dashes
- // or separators, followed immediately by the pdb's age, also in
- // uppercase hexadecimal form. For older pdb files which have no guid,
- // the identifier is the pdb's 32-bit signature value, in zero-padded
- // hexadecimal form, followed immediately by the pdb's age, in lowercase
- // hexadecimal form.
- wstring debug_identifier;
-
- // A string identifying the cpu that the pdb is associated with.
- // Currently, this may be "x86" or "unknown".
- wstring cpu;
-};
-
-// A structure that carries information that identifies a PE file,
-// either an EXE or a DLL.
-struct PEModuleInfo {
- // The basename of the PE file.
- wstring code_file;
-
- // The PE file's code identifier, which consists of its timestamp
- // and file size concatenated together into a single hex string.
- // (The fields IMAGE_OPTIONAL_HEADER::SizeOfImage and
- // IMAGE_FILE_HEADER::TimeDateStamp, as defined in the ImageHlp
- // documentation.) This is not well documented, if it's documented
- // at all, but it's what symstore does and what DbgHelp supports.
- wstring code_identifier;
-};
-
-class PDBSourceLineWriter {
- public:
- enum FileFormat {
- PDB_FILE, // a .pdb file containing debug symbols
- EXE_FILE, // a .exe or .dll file
- ANY_FILE // try PDB_FILE and then EXE_FILE
- };
-
- explicit PDBSourceLineWriter();
- ~PDBSourceLineWriter();
-
- // Opens the given file. For executable files, the corresponding pdb
- // file must be available; Open will be if it is not.
- // If there is already a pdb file open, it is automatically closed.
- // Returns true on success.
- bool Open(const wstring &file, FileFormat format);
-
- // Sets the code file full path. This is optional for 32-bit modules. It is
- // also optional for 64-bit modules when there is an executable file stored
- // in the same directory as the PDB file. It is only required for 64-bit
- // modules when the executable file is not in the same location as the PDB
- // file and it must be called after Open() and before WriteMap().
- // If Open() was called for an executable file, then it is an error to call
- // SetCodeFile() with a different file path and it will return false.
- bool SetCodeFile(const wstring &exe_file);
-
- // Writes a map file from the current pdb file to the given file stream.
- // Returns true on success.
- bool WriteMap(FILE *map_file);
-
- // Closes the current pdb file and its associated resources.
- void Close();
-
- // Retrieves information about the module's debugging file. Returns
- // true on success and false on failure.
- bool GetModuleInfo(PDBModuleInfo *info);
-
- // Retrieves information about the module's PE file. Returns
- // true on success and false on failure.
- bool GetPEInfo(PEModuleInfo *info);
-
- // Sets uses_guid to true if the opened file uses a new-style CodeView
- // record with a 128-bit GUID, or false if the opened file uses an old-style
- // CodeView record. When no GUID is available, a 32-bit signature should be
- // used to identify the module instead. If the information cannot be
- // determined, this method returns false.
- bool UsesGUID(bool *uses_guid);
-
- private:
- // Outputs the line/address pairs for each line in the enumerator.
- // Returns true on success.
- bool PrintLines(IDiaEnumLineNumbers *lines);
-
- // Outputs a function address and name, followed by its source line list.
- // block can be the same object as function, or it can be a reference
- // to a code block that is lexically part of this function, but
- // resides at a separate address.
- // Returns true on success.
- bool PrintFunction(IDiaSymbol *function, IDiaSymbol *block);
-
- // Outputs all functions as described above. Returns true on success.
- bool PrintFunctions();
-
- // Outputs all of the source files in the session's pdb file.
- // Returns true on success.
- bool PrintSourceFiles();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. For x86 data stored in
- // .pdb files. Returns true on success.
- bool PrintFrameDataUsingPDB();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. For x64 data stored in
- // .exe, .dll files. Returns true on success.
- bool PrintFrameDataUsingEXE();
-
- // Outputs all of the frame information necessary to construct stack
- // backtraces in the absence of frame pointers. Returns true on success.
- bool PrintFrameData();
-
- // Outputs a single public symbol address and name, if the symbol corresponds
- // to a code address. Returns true on success. If symbol is does not
- // correspond to code, returns true without outputting anything.
- bool PrintCodePublicSymbol(IDiaSymbol *symbol);
-
- // Outputs a line identifying the PDB file that is being dumped, along with
- // its uuid and age.
- bool PrintPDBInfo();
-
- // Outputs a line identifying the PE file corresponding to the PDB
- // file that is being dumped, along with its code identifier,
- // which consists of its timestamp and file size.
- bool PrintPEInfo();
-
- // Returns true if this filename has already been seen,
- // and an ID is stored for it, or false if it has not.
- bool FileIDIsCached(const wstring &file) {
- return unique_files_.find(file) != unique_files_.end();
- }
-
- // Cache this filename and ID for later reuse.
- void CacheFileID(const wstring &file, DWORD id) {
- unique_files_[file] = id;
- }
-
- // Store this ID in the cache as a duplicate for this filename.
- void StoreDuplicateFileID(const wstring &file, DWORD id) {
- unordered_map<wstring, DWORD>::iterator iter = unique_files_.find(file);
- if (iter != unique_files_.end()) {
- // map this id to the previously seen one
- file_ids_[id] = iter->second;
- }
- }
-
- // Given a file's unique ID, return the ID that should be used to
- // reference it. There may be multiple files with identical filenames
- // but different unique IDs. The cache attempts to coalesce these into
- // one ID per unique filename.
- DWORD GetRealFileID(DWORD id) {
- unordered_map<DWORD, DWORD>::iterator iter = file_ids_.find(id);
- if (iter == file_ids_.end())
- return id;
- return iter->second;
- }
-
- // Find the PE file corresponding to the loaded PDB file, and
- // set the code_file_ member. Returns false on failure.
- bool FindPEFile();
-
- // Returns the function name for a symbol. If possible, the name is
- // undecorated. If the symbol's decorated form indicates the size of
- // parameters on the stack, this information is returned in stack_param_size.
- // Returns true on success. If the symbol doesn't encode parameter size
- // information, stack_param_size is set to -1.
- static bool GetSymbolFunctionName(IDiaSymbol *function, BSTR *name,
- int *stack_param_size);
-
- // Returns the number of bytes of stack space used for a function's
- // parameters. function must have the tag SymTagFunction. In the event of
- // a failure, returns 0, which is also a valid number of bytes.
- static int GetFunctionStackParamSize(IDiaSymbol *function);
-
- // The filename of the PE file corresponding to the currently-open
- // pdb file.
- wstring code_file_;
-
- // The session for the currently-open pdb file.
- CComPtr<IDiaSession> session_;
-
- // The current output file for this WriteMap invocation.
- FILE *output_;
-
- // There may be many duplicate filenames with different IDs.
- // This maps from the DIA "unique ID" to a single ID per unique
- // filename.
- unordered_map<DWORD, DWORD> file_ids_;
- // This maps unique filenames to file IDs.
- unordered_map<wstring, DWORD> unique_files_;
-
- // This is used for calculating post-transform symbol addresses and lengths.
- ImageMap image_map_;
-
- // Disallow copy ctor and operator=
- PDBSourceLineWriter(const PDBSourceLineWriter&);
- void operator=(const PDBSourceLineWriter&);
-};
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_PDB_SOURCE_LINE_WRITER_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
deleted file mode 100644
index 9b6360726..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils-inl.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// string_utils-inl.h: Safer string manipulation on Windows, supporting
-// pre-MSVC8 environments.
-
-#ifndef COMMON_WINDOWS_STRING_UTILS_INL_H_
-#define COMMON_WINDOWS_STRING_UTILS_INL_H_
-
-#include <stdarg.h>
-#include <wchar.h>
-
-#include <string>
-
-// The "ll" printf format size specifier corresponding to |long long| was
-// intrudced in MSVC8. Earlier versions did not provide this size specifier,
-// but "I64" can be used to print 64-bit types. Don't use "I64" where "ll"
-// is available, in the event of oddball systems where |long long| is not
-// 64 bits wide.
-#if _MSC_VER >= 1400 // MSVC 2005/8
-#define WIN_STRING_FORMAT_LL "ll"
-#else // MSC_VER >= 1400
-#define WIN_STRING_FORMAT_LL "I64"
-#endif // MSC_VER >= 1400
-
-// A nonconforming version of swprintf, without the length argument, was
-// included with the CRT prior to MSVC8. Although a conforming version was
-// also available via an overload, it is not reliably chosen. _snwprintf
-// behaves as a standards-confirming swprintf should, so force the use of
-// _snwprintf when using older CRTs.
-#if _MSC_VER < 1400 // MSVC 2005/8
-#define swprintf _snwprintf
-#else
-// For MSVC8 and newer, swprintf_s is the recommended method. Conveniently,
-// it takes the same argument list as swprintf.
-#define swprintf swprintf_s
-#endif // MSC_VER < 1400
-
-namespace google_breakpad {
-
-using std::string;
-using std::wstring;
-
-class WindowsStringUtils {
- public:
- // Roughly equivalent to MSVC8's wcscpy_s, except pre-MSVC8, this does
- // not fail if source is longer than destination_size. The destination
- // buffer is always 0-terminated.
- static void safe_wcscpy(wchar_t *destination, size_t destination_size,
- const wchar_t *source);
-
- // Roughly equivalent to MSVC8's wcsncpy_s, except that _TRUNCATE cannot
- // be passed directly, and pre-MSVC8, this will not fail if source or count
- // are longer than destination_size. The destination buffer is always
- // 0-terminated.
- static void safe_wcsncpy(wchar_t *destination, size_t destination_size,
- const wchar_t *source, size_t count);
-
- // Performs multi-byte to wide character conversion on C++ strings, using
- // mbstowcs_s (MSVC8) or mbstowcs (pre-MSVC8). Returns false on failure,
- // without setting wcs.
- static bool safe_mbstowcs(const string &mbs, wstring *wcs);
-
- // The inverse of safe_mbstowcs.
- static bool safe_wcstombs(const wstring &wcs, string *mbs);
-
- // Returns the base name of a file, e.g. strips off the path.
- static wstring GetBaseName(const wstring &filename);
-
- private:
- // Disallow instantiation and other object-based operations.
- WindowsStringUtils();
- WindowsStringUtils(const WindowsStringUtils&);
- ~WindowsStringUtils();
- void operator=(const WindowsStringUtils&);
-};
-
-// static
-inline void WindowsStringUtils::safe_wcscpy(wchar_t *destination,
- size_t destination_size,
- const wchar_t *source) {
-#if _MSC_VER >= 1400 // MSVC 2005/8
- wcscpy_s(destination, destination_size, source);
-#else // _MSC_VER >= 1400
- // Pre-MSVC 2005/8 doesn't have wcscpy_s. Simulate it with wcsncpy.
- // wcsncpy doesn't 0-terminate the destination buffer if the source string
- // is longer than size. Ensure that the destination is 0-terminated.
- wcsncpy(destination, source, destination_size);
- if (destination && destination_size)
- destination[destination_size - 1] = 0;
-#endif // _MSC_VER >= 1400
-}
-
-// static
-inline void WindowsStringUtils::safe_wcsncpy(wchar_t *destination,
- size_t destination_size,
- const wchar_t *source,
- size_t count) {
-#if _MSC_VER >= 1400 // MSVC 2005/8
- wcsncpy_s(destination, destination_size, source, count);
-#else // _MSC_VER >= 1400
- // Pre-MSVC 2005/8 doesn't have wcsncpy_s. Simulate it with wcsncpy.
- // wcsncpy doesn't 0-terminate the destination buffer if the source string
- // is longer than size. Ensure that the destination is 0-terminated.
- if (destination_size < count)
- count = destination_size;
-
- wcsncpy(destination, source, count);
- if (destination && count)
- destination[count - 1] = 0;
-#endif // _MSC_VER >= 1400
-}
-
-} // namespace google_breakpad
-
-#endif // COMMON_WINDOWS_STRING_UTILS_INL_H_
diff --git a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc b/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
deleted file mode 100644
index 272800035..000000000
--- a/toolkit/crashreporter/google-breakpad/src/common/windows/string_utils.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <cassert>
-#include <vector>
-
-#include "common/windows/string_utils-inl.h"
-
-namespace google_breakpad {
-
-// static
-wstring WindowsStringUtils::GetBaseName(const wstring &filename) {
- wstring base_name(filename);
- size_t slash_pos = base_name.find_last_of(L"/\\");
- if (slash_pos != wstring::npos) {
- base_name.erase(0, slash_pos + 1);
- }
- return base_name;
-}
-
-// static
-bool WindowsStringUtils::safe_mbstowcs(const string &mbs, wstring *wcs) {
- assert(wcs);
-
- // First, determine the length of the destination buffer.
- size_t wcs_length;
-
-#if _MSC_VER >= 1400 // MSVC 2005/8
- errno_t err;
- if ((err = mbstowcs_s(&wcs_length, NULL, 0, mbs.c_str(), _TRUNCATE)) != 0) {
- return false;
- }
- assert(wcs_length > 0);
-#else // _MSC_VER >= 1400
- if ((wcs_length = mbstowcs(NULL, mbs.c_str(), mbs.length())) == (size_t)-1) {
- return false;
- }
-
- // Leave space for the 0-terminator.
- ++wcs_length;
-#endif // _MSC_VER >= 1400
-
- std::vector<wchar_t> wcs_v(wcs_length);
-
- // Now, convert.
-#if _MSC_VER >= 1400 // MSVC 2005/8
- if ((err = mbstowcs_s(NULL, &wcs_v[0], wcs_length, mbs.c_str(),
- _TRUNCATE)) != 0) {
- return false;
- }
-#else // _MSC_VER >= 1400
- if (mbstowcs(&wcs_v[0], mbs.c_str(), mbs.length()) == (size_t)-1) {
- return false;
- }
-
- // Ensure presence of 0-terminator.
- wcs_v[wcs_length - 1] = '\0';
-#endif // _MSC_VER >= 1400
-
- *wcs = &wcs_v[0];
- return true;
-}
-
-// static
-bool WindowsStringUtils::safe_wcstombs(const wstring &wcs, string *mbs) {
- assert(mbs);
-
- // First, determine the length of the destination buffer.
- size_t mbs_length;
-
-#if _MSC_VER >= 1400 // MSVC 2005/8
- errno_t err;
- if ((err = wcstombs_s(&mbs_length, NULL, 0, wcs.c_str(), _TRUNCATE)) != 0) {
- return false;
- }
- assert(mbs_length > 0);
-#else // _MSC_VER >= 1400
- if ((mbs_length = wcstombs(NULL, wcs.c_str(), wcs.length())) == (size_t)-1) {
- return false;
- }
-
- // Leave space for the 0-terminator.
- ++mbs_length;
-#endif // _MSC_VER >= 1400
-
- std::vector<char> mbs_v(mbs_length);
-
- // Now, convert.
-#if _MSC_VER >= 1400 // MSVC 2005/8
- if ((err = wcstombs_s(NULL, &mbs_v[0], mbs_length, wcs.c_str(),
- _TRUNCATE)) != 0) {
- return false;
- }
-#else // _MSC_VER >= 1400
- if (wcstombs(&mbs_v[0], wcs.c_str(), wcs.length()) == (size_t)-1) {
- return false;
- }
-
- // Ensure presence of 0-terminator.
- mbs_v[mbs_length - 1] = '\0';
-#endif // _MSC_VER >= 1400
-
- *mbs = &mbs_v[0];
- return true;
-}
-
-} // namespace google_breakpad